Merge branch 'master' into contact

Conflicts:
	static/js/controllers.js
	templates/base.html
This commit is contained in:
yackob03 2014-01-15 14:32:51 -05:00
commit 82c4c8a28b
78 changed files with 5071 additions and 1953 deletions

File diff suppressed because it is too large Load diff

13
static/js/bootstrap.js vendored Normal file
View file

@ -0,0 +1,13 @@
$.ajax({
type: 'GET',
async: false,
url: '/api/discovery',
success: function(data) {
window.__endpoints = data.endpoints;
},
error: function() {
setTimeout(function() {
$('#couldnotloadModal').modal({});
}, 250);
}
});

File diff suppressed because it is too large Load diff

View file

@ -1,10 +1,37 @@
/**
* Bind polyfill from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Compatibility
*/
if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
if (typeof this !== "function") {
// closest thing possible to the ECMAScript 5 internal IsCallable function
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function () {},
fBound = function () {
return fToBind.apply(this instanceof fNOP && oThis
? this
: oThis,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
};
}
var DEPTH_HEIGHT = 100;
var DEPTH_WIDTH = 132;
/**
* Based off of http://mbostock.github.io/d3/talk/20111018/tree.html by Mike Bostock (@mbostock)
*/
function ImageHistoryTree(namespace, name, images, formatComment, formatTime) {
function ImageHistoryTree(namespace, name, images, formatComment, formatTime, formatCommand) {
/**
* The namespace of the repo.
*/
@ -30,6 +57,11 @@ function ImageHistoryTree(namespace, name, images, formatComment, formatTime) {
*/
this.formatTime_ = formatTime;
/**
* Method to invoke to format the command for an image.
*/
this.formatCommand_ = formatCommand;
/**
* The current tag (if any).
*/
@ -40,6 +72,11 @@ function ImageHistoryTree(namespace, name, images, formatComment, formatTime) {
*/
this.currentImage_ = null;
/**
* The currently highlighted node (if any).
*/
this.currentNode_ = null;
/**
* Counter for creating unique IDs.
*/
@ -54,7 +91,7 @@ ImageHistoryTree.prototype.calculateDimensions_ = function(container) {
var cw = Math.max(document.getElementById(container).clientWidth, this.maxWidth_ * DEPTH_WIDTH);
var ch = this.maxHeight_ * (DEPTH_HEIGHT + 10);
var margin = { top: 40, right: 20, bottom: 20, left: 40 };
var margin = { top: 40, right: 20, bottom: 20, left: 80 };
var m = [margin.top, margin.right, margin.bottom, margin.left];
var w = cw - m[1] - m[3];
var h = ch - m[0] - m[2];
@ -69,6 +106,25 @@ ImageHistoryTree.prototype.calculateDimensions_ = function(container) {
};
ImageHistoryTree.prototype.setupOverscroll_ = function() {
var container = this.container_;
var that = this;
var overscroll = $('#' + container).overscroll();
overscroll.on('overscroll:dragstart', function() {
$(that).trigger({
'type': 'hideTagMenu'
});
});
overscroll.on('scroll', function() {
$(that).trigger({
'type': 'hideTagMenu'
});
});
};
/**
* Updates the dimensions of the tree.
*/
@ -86,17 +142,22 @@ ImageHistoryTree.prototype.updateDimensions_ = function() {
$('#' + container).removeOverscroll();
var viewportHeight = $(window).height();
var boundingBox = document.getElementById(container).getBoundingClientRect();
document.getElementById(container).style.maxHeight = (viewportHeight - boundingBox.top - 110) + 'px';
$('#' + container).overscroll();
document.getElementById(container).style.maxHeight = (viewportHeight - boundingBox.top - 150) + 'px';
this.setupOverscroll_();
// Update the tree.
var rootSvg = this.rootSvg_;
var tree = this.tree_;
var vis = this.vis_;
var ow = w + m[1] + m[3];
var oh = h + m[0] + m[2];
rootSvg
.attr("width", w + m[1] + m[3])
.attr("height", h + m[0] + m[2]);
.attr("width", ow)
.attr("height", oh)
.attr("style", "width: " + ow + "px; height: " + oh + "px");
tree.size([w, h]);
vis.attr("transform", "translate(" + m[3] + "," + m[0] + ")");
@ -131,6 +192,8 @@ ImageHistoryTree.prototype.draw = function(container) {
var formatComment = this.formatComment_;
var formatTime = this.formatTime_;
var formatCommand = this.formatCommand_;
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-1, 24])
@ -156,8 +219,10 @@ ImageHistoryTree.prototype.draw = function(container) {
if (d.image.comment) {
html += '<span class="comment">' + formatComment(d.image.comment) + '</span>';
}
html += '<span class="created">' + formatTime(d.image.created) + '</span>';
html += '<span class="full-id">' + d.image.id + '</span>';
if (d.image.command && d.image.command.length) {
html += '<span class="command info-line"><i class="fa fa-terminal"></i>' + formatCommand(d.image) + '</span>';
}
html += '<span class="created info-line"><i class="fa fa-calendar"></i>' + formatTime(d.image.created) + '</span>';
return html;
})
@ -178,8 +243,7 @@ ImageHistoryTree.prototype.draw = function(container) {
this.root_.y0 = 0;
this.setTag_(this.currentTag_);
$('#' + container).overscroll();
this.setupOverscroll_();
};
@ -208,6 +272,23 @@ ImageHistoryTree.prototype.setImage = function(imageId) {
};
/**
* Updates the highlighted path in the tree.
*/
ImageHistoryTree.prototype.setHighlightedPath_ = function(image) {
if (this.currentNode_) {
this.markPath_(this.currentNode_, false);
}
var imageByDBID = this.imageByDBID_;
var currentNode = imageByDBID[image.dbid];
if (currentNode) {
this.markPath_(currentNode, true);
this.currentNode_ = currentNode;
}
};
/**
* Returns the ancestors of the given image.
*/
@ -445,26 +526,15 @@ ImageHistoryTree.prototype.setTag_ = function(tagName) {
// Save the current tag.
var previousTagName = this.currentTag_;
this.currentTag_ = tagName;
this.currentImage_ = null;
// Update the state of each existing node to no longer be highlighted.
var previousImage = this.findImage_(function(image) {
return image.tags.indexOf(previousTagName || '(no tag specified)') >= 0;
});
if (previousImage) {
var currentNode = imageByDBID[previousImage.dbid];
this.markPath_(currentNode, false);
}
// Find the new current image (if any).
this.currentImage_ = this.findImage_(function(image) {
// Update the path.
var tagImage = this.findImage_(function(image) {
return image.tags.indexOf(tagName || '(no tag specified)') >= 0;
});
// Update the state of the new node path.
if (this.currentImage_) {
var currentNode = imageByDBID[this.currentImage_.dbid];
this.markPath_(currentNode, true);
if (tagImage) {
this.setHighlightedPath_(tagImage);
}
// Ensure that the children are in the correct order.
@ -508,7 +578,9 @@ ImageHistoryTree.prototype.setImage_ = function(imageId) {
return;
}
this.setHighlightedPath_(newImage);
this.currentImage_ = newImage;
this.currentTag_ = null;
this.update_(this.root_);
};
@ -637,7 +709,7 @@ ImageHistoryTree.prototype.update_ = function(source) {
if (tag == currentTag) {
kind = 'success';
}
html += '<span class="label label-' + kind + ' tag" data-tag="' + tag + '">' + tag + '</span>';
html += '<span class="label label-' + kind + ' tag" data-tag="' + tag + '"">' + tag + '</span>';
}
return html;
});
@ -649,6 +721,19 @@ ImageHistoryTree.prototype.update_ = function(source) {
if (tag) {
that.changeTag_(tag);
}
})
.on("contextmenu", function(d, e) {
d3.event.preventDefault();
var tag = this.getAttribute('data-tag');
if (tag) {
$(that).trigger({
'type': 'showTagMenu',
'tag': tag,
'clientX': d3.event.clientX,
'clientY': d3.event.clientY
});
}
});
// Ensure the tags are visible.