Page Menu
Home
DevCentral
Search
Configure Global Search
Log In
Files
F11726238
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
11 KB
Referenced Files
None
Subscribers
None
View Options
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"> <%= project.name %> :: <em><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></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
Details
Attached
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)
Attached To
Mode
rTOMMY Tommy
Attached
Detach File
Event Timeline
Log In to Comment