Merge branch 'master' into contact
Conflicts: static/js/controllers.js templates/base.html
This commit is contained in:
commit
82c4c8a28b
78 changed files with 5071 additions and 1953 deletions
719
static/js/app.js
719
static/js/app.js
File diff suppressed because it is too large
Load diff
13
static/js/bootstrap.js
vendored
Normal file
13
static/js/bootstrap.js
vendored
Normal 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
|
@ -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.
|
||||
|
|
Reference in a new issue