Page MenuHomeDevCentral

No OneTemporary

diff --git a/public/styles.css b/public/styles.css
index 919480c..26c96cf 100644
--- a/public/styles.css
+++ b/public/styles.css
@@ -1,95 +1,148 @@
-body{
- padding:0px;
- margin:0px;
+@-webkit-keyframes warning {
+ 0% {opacity: 1}
+ 50% {opacity: 0.75}
+ 100% {opacity: 1}
}
-#wrapper{
- width:100%;
- margin:0px auto;
+html {
+ background: #000;
+ font: 14px "Helvetica Neue", Arial, sans-serif;
+ height: 100%;
}
-.project{
- position:relative;
- width:25%;
- height: 225px;
- border-left:1px solid black;
- border-bottom: 1px solid black;
- margin-left: -1px;
- float: left;
+ body {
+ height: 100%;
+ margin: 0px;
+ overflow: auto;
}
-
-.green{
- background-color:#00ff33;
-}
-.yellow_green{
- background-color:#ccff66;
-}
+ #wrapper {
+ box-sizing: border-box;
+ border: 10px solid #000;
+ height: 100%;
+ }
-.red{
- background-color: red;
-}
+ .ipad-scale #wrapper {
+ -webkit-transform: scaleX(0.533);
+ -webkit-transform-origin-x: 0;
+ width: 187.5%;
+ }
-.yellow{
- background-color: yellow;
-}
+ .project {
+ background-image:
+ -webkit-linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.25));
+ border: 5px solid #000;
+ box-sizing: border-box;
+ float: left;
+ min-height: 45px;
+ padding: 5px 10px;
+ position: relative;
+ width: 33.3%;
+ }
-.yellow_orange{
- background-color: #ffb428;
-}
+ @media screen and (max-width: 800px) {
+ .project {
+ width: 50%;
+ }
+ }
-.orange{
- background-color: #ff6600;
-}
+ @media screen and (max-width: 500px) {
+ .project {
+ width: 100%;
+ }
+ }
-.inactive{
- background-color:gray;
-}
+ .project.with-details {
+ z-index: 2;
+ }
-.build_number{
- font-size:55px;
- padding:0px;
- margin: 0px;
- position:absolute;
- top:5px;
- left:5px;
- font-family: georgia;
-}
+ .project.building {background-color: #999;}
+ .project.best {background-color: #0f0;}
+ .project.better {background-color: #8f0;}
+ .project.good {background-color: #ff0;}
+ .project.bad {background-color: #f80;}
+ .project.worse {background-color: #f00;}
+ .project.worst {
+ -webkit-animation: warning 1s infinite ease-in-out;
+ background-color: #f00;
+ z-index: 1;
+ }
-.build_number a{
- text-decoration:none;
- color: black;
-}
+ .project > .heading {
+ font-size: 18px;
+ }
-.build_number a:hover{
- text-decoration:underline;
-}
+ .project > .heading > .name {
+ color: #fff;
+ display: inline-block;
+ font-weight: bold;
+ max-width: 80%;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ text-shadow: 0 1px 1px rgba(0, 0, 0, 0.5);
+ white-space: nowrap;
+ }
-.project_name{
- position:absolute;
- font-family: helvetica;
- font-size: 12px;
- bottom:0px;
- padding:15px 0px;
- background: black;
- color: white;
- width: 100%;
- border-top: 1px solid silver;
- border-bottom: 1px solid silver;
-}
+ .project > .heading > .build-number {
+ color: #000;
+ float: right;
+ font-weight: bold;
+ text-decoration: none;
+ opacity: 0.33;
+ }
-.project_name a{
- color: yellow;
- text-decoration:none;
-}
+ .project > .details {
+ background: rgba(0, 0, 0, 0.9);
+ border-radius: 3px;
+ box-shadow:
+ 0 0 1px rgba(255, 255, 255, 0.5) inset,
+ 0 3px 10px #000;
+ color: #fff;
+ display: none;
+ left: 10px;
+ padding: 10px;
+ position: absolute;
+ top: 35px;
+ }
-.build_stats{
- padding-top:80px;
- font-family:helvetica;
- font-size:12px;
-}
+ .project.with-details > .details {
+ display: block;
+ }
-.row{
- width:100%;
- display: table-row;
-}
+ .project > .details:before {
+ border: 8px solid transparent;
+ bottom: 100%;
+ border-bottom-color: rgba(0, 0, 0, 0.8);
+ content: " ";
+ left: 4%;
+ margin-bottom: -3px;
+ margin-left: -4px;
+ position: absolute;
+ }
+
+ .project > .details > .health {
+ margin: 10px;
+ white-space: nowrap;
+ }
+
+ .project > .details > .actions {
+ margin: 5px;
+ text-align: center;
+ }
+
+ .project > .details > .actions > a {
+ background: #444;
+ border-radius: 15px;
+ box-shadow:
+ 0 1px 0 rgba(255, 255, 255, 0.3) inset,
+ 0 1px 0 #000;
+ color: #fff;
+ display: inline-block;
+ font-size: 10px;
+ letter-spacing: 1px;
+ margin-right: 2px;
+ padding: 2px 10px;
+ text-decoration: none;
+ text-shadow: 0 1px 0 #000;
+ text-transform: uppercase;
+ }
diff --git a/tommy.rb b/tommy.rb
index 95b906e..ba64110 100644
--- a/tommy.rb
+++ b/tommy.rb
@@ -1,75 +1,77 @@
require 'sinatra'
require 'rest-client'
require 'active_support/all'
require 'crack'
require 'hashie'
require 'erb'
HUDSON_URL = ENV['HUDSON_URL'] || 'http://username:password@my.hudsonurl.com'
class Project < Hashie::Dash
property :name
property :build_score
property :last_build_number
property :last_build_url
property :last_stable_build
property :health_report
property :last_complete_url
property :last_failed_url
property :colour
def self.parse_incoming_json(json)
returned_projects = []
projects = json['jobs']
projects.each do |project|
returned_projects << Project.new( :name => project['displayName'].gsub('-', ' '),
:build_score => project['healthReport'].first['score'].to_i,
:last_build_number => project['builds'].first['number'],
:last_build_url => (project['lastBuild'].blank? ? "" : project['lastBuild']['url']),
:last_stable_build => (project['lastStableBuild'].blank? ? "" : project['lastStableBuild']['number']),
:health_report => project['healthReport'].first['description'],
:last_complete_url => (project['lastCompletedBuild'].blank? ? "" : project['lastCompletedBuild']['url']),
:last_failed_url => (project['lastFailedBuild'].blank? ? "" : project['lastFailedBuild']['url'] ),
:colour => project['color'])
end
return returned_projects
end
def is_green?
self.last_stable_build == self.last_build_number
end
def is_building?
self.colour.include?('anime')
end
end
get '/' do
json = RestClient::Resource.new("#{HUDSON_URL}/api/json?depth=1")
@projects = Project.parse_incoming_json(Crack::JSON.parse(json.get))
erb :index
end
helpers do
def css_for_project(project)
score = project.build_score
if project.is_green?
if score == 100
- "green"
+ "best"
elsif score >= 80
- "yellow_green"
+ "better"
elsif score >= 60
- "yellow"
+ "good"
elsif score >= 40
- "yellow_orange"
+ "bad"
elsif score >= 20
- "orange"
+ "worse"
end
+ elsif project.is_building?
+ "building"
else
- "red"
+ "worst"
end
end
-end
\ No newline at end of file
+end
diff --git a/views/index.erb b/views/index.erb
index a0b720d..ef11adf 100644
--- a/views/index.erb
+++ b/views/index.erb
@@ -1,32 +1,81 @@
+<!DOCTYPE html>
+
<html>
-<head>
- <title>Tommy</title>
- <meta http-equiv="refresh" content="30;url=/">
- <link href='styles.css' rel='stylesheet' type='text/css' />
- <script src='https://ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js' type='text/javascript'></script>
- <script>
- function show_stats(element){
- $(element).find('.build_stats').toggle();
- };
- </script>
-</head>
-<body>
- <div id="wrapper">
- <% @projects.in_groups_of(4) do |group| %>
- <% group.each_with_index do |project, index| %>
+ <head>
+ <meta charset="utf8" />
+ <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" />
+ <meta http-equiv="refresh" content="30;url=/" />
+
+ <title>Tommy</title>
+
+ <link href="styles.css" rel="stylesheet" type="text/css" />
+ </head>
+
+ <body>
+ <div id="wrapper">
+ <% @projects.each do |project| %>
<% if project %>
- <span class="project <%= css_for_project(project) %>" onclick="show_stats(this);">
- <p class="build_number"><a href="<%= project.last_build_url %>" target="_blank" title="View Build">#<%= project.last_build_number %></a></p>
- <ul class="build_stats" style="display:none;">
- <li><%= project.health_report %></li>
- </ul>
- <p class="project_name">&nbsp;&nbsp;&nbsp;<%= project.name %> :: <em><a href="<%= project.last_build_url %>" target="_blank">build</a> &middot; <a href="<%= project.last_complete_url %>" target="_blank">complete</a> &middot; <a href="<%= project.last_failed_url %>" target="_blank">failed</a></em></p>
- </span>
+ <div class="project <%= css_for_project(project) %>">
+ <div class="heading">
+ <span class="name"><%= project.name %></span>
+ <a href="<%= project.last_build_url %>" target="_blank" class="build-number"><%= project.last_build_number %></a>
+ </div>
+
+ <div class="details">
+ <div class="health"><%= project.health_report %></div>
+
+ <div class="actions">
+ <a href="<%= project.last_build_url %>" target="_blank">Build</a>
+ <a href="<%= project.last_complete_url %>" target="_blank">Complete</a>
+ <a href="<%= project.last_failed_url %>" target="_blank">Failed</a>
+ </div>
+ </div>
+ </div>
<% else %>
- <span class="project inactive"></span>
+ <!--No project-->
<% end %>
<% end %>
- <% end %>
- </div>
-</body>
+ </div>
+
+ <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
+ <script type="text/javascript">
+ var DETAILS_CLASS = 'with-details';
+
+ var projects = $('.project');
+ var doc = $(document);
+
+ function toggleDetails(e) {
+ var target = $(this);
+ var hadDetails = target.hasClass(DETAILS_CLASS);
+ projects.removeClass(DETAILS_CLASS);
+ if (!hadDetails) target.addClass(DETAILS_CLASS);
+ }
+
+ doc.on('click', '.project', toggleDetails);
+ doc.on('touchstart', '.project', toggleDetails);
+
+ doc.on('keydown', function(e) {
+ if (e.keyCode === 27) projects.removeClass(DETAILS_CLASS);
+ });
+
+ // Always take up the full screen.
+ function adjustProjectHeights() {
+ var _firstTop = NaN;
+ for (var howManyAcross = 0; howManyAcross < projects.length; howManyAcross++) {
+ var offsetTop = $(projects[howManyAcross]).offset().top;
+ if (isNaN(_firstTop)) _firstTop = offsetTop;
+ if (offsetTop !== _firstTop) break;
+ }
+
+ projects.height(projects.parent().height() / (projects.length / howManyAcross));
+ }
+
+ $(window).on('resize', adjustProjectHeights);
+ adjustProjectHeights();
+
+ // An iPod driving an HD monitor will stretch the image.
+ // Compensate by shrinking it a bit.
+ if (~location.search.indexOf('ipad')) $('html').addClass('ipad-scale');
+ </script>
+ </body>
</html>

File Metadata

Mime Type
text/x-diff
Expires
Fri, Sep 19, 01:45 (1 d, 4 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2992040
Default Alt Text
(11 KB)

Event Timeline