New view repo UI
This commit is contained in:
parent
a7f5b5e033
commit
90759e0cb2
4 changed files with 207 additions and 91 deletions
|
@ -332,29 +332,27 @@ p.editable:hover i {
|
||||||
|
|
||||||
.tag-dropdown {
|
.tag-dropdown {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 6px;
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
margin-right: 15px;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
font-size: 1.15em;
|
font-size: 1.15em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tag-dropdown i.icon-bookmark {
|
.right-title {
|
||||||
font-size: 125%;
|
display: inline-block;
|
||||||
position: relative;
|
float: right;
|
||||||
margin-left: 2px;
|
padding: 4px;
|
||||||
margin-right: 4px;
|
font-size: 12px;
|
||||||
|
color: #aaa;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tag-dropdown i.icon-bookmark .tag-count {
|
.tag-dropdown .tag-count {
|
||||||
color: #aaa;
|
|
||||||
position: absolute;
|
|
||||||
top: 0px;
|
|
||||||
left: 0px;
|
|
||||||
font-size: 55%;
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 14px;
|
margin-left: 4px;
|
||||||
text-align: center;
|
margin-right: 6px;
|
||||||
|
padding-right: 10px;
|
||||||
|
border-right: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-dropdown a {
|
||||||
|
color: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-body textarea {
|
.modal-body textarea {
|
||||||
|
@ -706,6 +704,11 @@ p.editable:hover i {
|
||||||
stroke-width: 2.5px;
|
stroke-width: 2.5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#image-history-container .node text.current {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
#image-history-container .node text {
|
#image-history-container .node text {
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
|
@ -196,23 +196,7 @@ function LandingCtrl($scope, $timeout, Restangular, UserService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function RepoCtrl($scope, Restangular, $routeParams, $rootScope) {
|
function RepoCtrl($scope, Restangular, $routeParams, $rootScope) {
|
||||||
var tabs = ['current-image', 'image-history'];
|
|
||||||
|
|
||||||
$rootScope.title = 'Loading...';
|
$rootScope.title = 'Loading...';
|
||||||
|
|
||||||
$scope.showTab = function(tabName) {
|
|
||||||
for (var i = 0; i < tabs.length; ++i) {
|
|
||||||
$('#' + tabs[i]).hide();
|
|
||||||
$('#' + tabs[i] + '-tab').removeClass('active');
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#' + tabName).show();
|
|
||||||
$('#' + tabName + '-tab').addClass('active');
|
|
||||||
|
|
||||||
if (tabName == 'image-history') {
|
|
||||||
$scope.listImages();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.editDescription = function() {
|
$scope.editDescription = function() {
|
||||||
if (!$scope.repo.can_write) { return; }
|
if (!$scope.repo.can_write) { return; }
|
||||||
|
@ -242,7 +226,7 @@ function RepoCtrl($scope, Restangular, $routeParams, $rootScope) {
|
||||||
return getMarkedDown(getFirstTextLine(commentString));
|
return getMarkedDown(getFirstTextLine(commentString));
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.getTimeSince= function(createdTime) {
|
$scope.getTimeSince = function(createdTime) {
|
||||||
return moment($scope.parseDate(createdTime)).fromNow();
|
return moment($scope.parseDate(createdTime)).fromNow();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -257,12 +241,35 @@ function RepoCtrl($scope, Restangular, $routeParams, $rootScope) {
|
||||||
var imageFetch = Restangular.one('repository/' + namespace + '/' + name + '/image');
|
var imageFetch = Restangular.one('repository/' + namespace + '/' + name + '/image');
|
||||||
imageFetch.get().then(function(resp) {
|
imageFetch.get().then(function(resp) {
|
||||||
$scope.imageHistory = resp.images;
|
$scope.imageHistory = resp.images;
|
||||||
var tree = new ImageHistoryTree(namespace, name, resp.images, $scope.currentTag,
|
$scope.tree = new ImageHistoryTree(namespace, name, resp.images, $scope.currentTag,
|
||||||
$scope.getCommentFirstLine, $scope.getTimeSince);
|
$scope.getCommentFirstLine, $scope.getTimeSince);
|
||||||
tree.draw('image-history-container');
|
|
||||||
|
$scope.tree.draw('image-history-container');
|
||||||
|
$($scope.tree).bind('tagChanged', function(e) {
|
||||||
|
$scope.$apply(function() { $scope.setTag(e.tag); });
|
||||||
|
});
|
||||||
|
$($scope.tree).bind('imageChanged', function(e) {
|
||||||
|
$scope.$apply(function() { $scope.setImage(e.image); });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.setImage = function(image) {
|
||||||
|
$scope.currentImage = image;
|
||||||
|
if ($scope.tree) {
|
||||||
|
$scope.tree.setImage($scope.currentImage.id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.setTag = function(tagName) {
|
||||||
|
var repo = $scope.repo;
|
||||||
|
$scope.currentTag = repo.tags[tagName] || repo.tags['latest'];
|
||||||
|
$scope.currentImage = $scope.currentTag.image;
|
||||||
|
if ($scope.tree) {
|
||||||
|
$scope.tree.setTag($scope.currentTag.name);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
$scope.getTagCount = function(repo) {
|
$scope.getTagCount = function(repo) {
|
||||||
if (!repo) { return 0; }
|
if (!repo) { return 0; }
|
||||||
var count = 0;
|
var count = 0;
|
||||||
|
@ -278,11 +285,13 @@ function RepoCtrl($scope, Restangular, $routeParams, $rootScope) {
|
||||||
|
|
||||||
$scope.loading = true;
|
$scope.loading = true;
|
||||||
|
|
||||||
|
// Fetch the repo.
|
||||||
var repositoryFetch = Restangular.one('repository/' + namespace + '/' + name);
|
var repositoryFetch = Restangular.one('repository/' + namespace + '/' + name);
|
||||||
repositoryFetch.get().then(function(repo) {
|
repositoryFetch.get().then(function(repo) {
|
||||||
$rootScope.title = namespace + '/' + name;
|
$rootScope.title = namespace + '/' + name;
|
||||||
$scope.repo = repo;
|
$scope.repo = repo;
|
||||||
$scope.currentTag = repo.tags[tag] || repo.tags['latest'];
|
$scope.currentTag = repo.tags[tag] || repo.tags['latest'];
|
||||||
|
$scope.setImage($scope.currentTag.image);
|
||||||
|
|
||||||
var clip = new ZeroClipboard($('#copyClipboard'), { 'moviePath': 'static/lib/ZeroClipboard.swf' });
|
var clip = new ZeroClipboard($('#copyClipboard'), { 'moviePath': 'static/lib/ZeroClipboard.swf' });
|
||||||
clip.on('complete', function() {
|
clip.on('complete', function() {
|
||||||
|
@ -302,6 +311,9 @@ function RepoCtrl($scope, Restangular, $routeParams, $rootScope) {
|
||||||
$scope.loading = false;
|
$scope.loading = false;
|
||||||
$rootScope.title = 'Unknown Repository';
|
$rootScope.title = 'Unknown Repository';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Fetch the image history.
|
||||||
|
$scope.listImages();
|
||||||
}
|
}
|
||||||
|
|
||||||
function RepoAdminCtrl($scope, Restangular, $routeParams, $rootScope) {
|
function RepoAdminCtrl($scope, Restangular, $routeParams, $rootScope) {
|
||||||
|
|
|
@ -57,14 +57,14 @@ ImageHistoryTree.prototype.draw = function(container) {
|
||||||
var width = document.getElementById(container).clientWidth;
|
var width = document.getElementById(container).clientWidth;
|
||||||
var height = Math.max(width * 0.625, this.maxHeight_ * (DEPTH_HEIGHT + 10));
|
var height = Math.max(width * 0.625, this.maxHeight_ * (DEPTH_HEIGHT + 10));
|
||||||
|
|
||||||
var margin = { top: 40, right: 60, bottom: 20, left: 60 };
|
var margin = { top: 40, right: 20, bottom: 20, left: 20 };
|
||||||
var m = [margin.top, margin.right, margin.bottom, margin.left];
|
var m = [margin.top, margin.right, margin.bottom, margin.left];
|
||||||
var w = width - m[1] - m[3];
|
var w = width - m[1] - m[3];
|
||||||
var h = height - m[0] - m[2];
|
var h = height - m[0] - m[2];
|
||||||
|
|
||||||
// Create the tree and all its components.
|
// Create the tree and all its components.
|
||||||
var tree = d3.layout.tree()
|
var tree = d3.layout.tree()
|
||||||
.size([h, w]);
|
.size([w, h]);
|
||||||
|
|
||||||
var diagonal = d3.svg.diagonal()
|
var diagonal = d3.svg.diagonal()
|
||||||
.projection(function(d) { return [d.x, d.y]; });
|
.projection(function(d) { return [d.x, d.y]; });
|
||||||
|
@ -110,10 +110,26 @@ ImageHistoryTree.prototype.draw = function(container) {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the current tag displayed in the tree.
|
||||||
|
*/
|
||||||
|
ImageHistoryTree.prototype.setTag = function(tagName) {
|
||||||
|
this.setTag_(tagName);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the current image displayed in the tree.
|
||||||
|
*/
|
||||||
|
ImageHistoryTree.prototype.setImage = function(imageId) {
|
||||||
|
this.setImage_(imageId);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the ancestors of the given image.
|
* Returns the ancestors of the given image.
|
||||||
*/
|
*/
|
||||||
ImageHistoryTree.prototype.getAncestors = function(image) {
|
ImageHistoryTree.prototype.getAncestors_ = function(image) {
|
||||||
var ancestorsString = image.ancestors;
|
var ancestorsString = image.ancestors;
|
||||||
|
|
||||||
// Remove the starting and ending /s.
|
// Remove the starting and ending /s.
|
||||||
|
@ -125,11 +141,37 @@ ImageHistoryTree.prototype.getAncestors = function(image) {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the current tag displayed in the tree and raises the event that the tag
|
||||||
|
* was changed.
|
||||||
|
*/
|
||||||
|
ImageHistoryTree.prototype.changeTag_ = function(tagName) {
|
||||||
|
$(this).trigger({
|
||||||
|
'type': 'tagChanged',
|
||||||
|
'tag': tagName
|
||||||
|
});
|
||||||
|
this.setTag_(tagName);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the current image displayed in the tree and raises the event that the image
|
||||||
|
* was changed.
|
||||||
|
*/
|
||||||
|
ImageHistoryTree.prototype.changeImage_ = function(imageId) {
|
||||||
|
$(this).trigger({
|
||||||
|
'type': 'imageChanged',
|
||||||
|
'image': this.findImage_(function(image) { return image.id == imageId; })
|
||||||
|
});
|
||||||
|
this.setImage_(imageId);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks the image node with whether it is the current image and/or highlighted.
|
* Marks the image node with whether it is the current image and/or highlighted.
|
||||||
*/
|
*/
|
||||||
ImageHistoryTree.prototype.markWithState_ = function(image, imageNode) {
|
ImageHistoryTree.prototype.markWithState_ = function(image, imageNode) {
|
||||||
var currentAncestors = this.getAncestors(this.currentImage_);
|
var currentAncestors = this.getAncestors_(this.currentImage_);
|
||||||
var isCurrent = image.id == this.currentImage_.id;
|
var isCurrent = image.id == this.currentImage_.id;
|
||||||
var isHighlighted = currentAncestors.indexOf(image.dbid.toString()) >= 0;
|
var isHighlighted = currentAncestors.indexOf(image.dbid.toString()) >= 0;
|
||||||
imageNode.highlighted = isHighlighted || isCurrent;
|
imageNode.highlighted = isHighlighted || isCurrent;
|
||||||
|
@ -169,7 +211,7 @@ ImageHistoryTree.prototype.buildRoot_ = function() {
|
||||||
for (var i = 0; i < this.images_.length; ++i) {
|
for (var i = 0; i < this.images_.length; ++i) {
|
||||||
var image = this.images_[i];
|
var image = this.images_[i];
|
||||||
var imageNode = imageByDBID[image.dbid];
|
var imageNode = imageByDBID[image.dbid];
|
||||||
var ancestors = this.getAncestors(image);
|
var ancestors = this.getAncestors_(image);
|
||||||
var immediateParent = ancestors[ancestors.length - 1] * 1;
|
var immediateParent = ancestors[ancestors.length - 1] * 1;
|
||||||
var parent = imageByDBID[immediateParent];
|
var parent = imageByDBID[immediateParent];
|
||||||
if (parent) {
|
if (parent) {
|
||||||
|
@ -192,6 +234,22 @@ ImageHistoryTree.prototype.buildRoot_ = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the image where the checker function returns true and returns it or null
|
||||||
|
* if none.
|
||||||
|
*/
|
||||||
|
ImageHistoryTree.prototype.findImage_ = function(checker) {
|
||||||
|
for (var i = 0; i < this.images_.length; ++i) {
|
||||||
|
var image = this.images_[i];
|
||||||
|
if (checker(image)) {
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the current tag displayed in the tree.
|
* Sets the current tag displayed in the tree.
|
||||||
*/
|
*/
|
||||||
|
@ -199,16 +257,13 @@ ImageHistoryTree.prototype.setTag_ = function(tagName) {
|
||||||
this.currentTag_ = tagName;
|
this.currentTag_ = tagName;
|
||||||
|
|
||||||
// Find the new current image.
|
// Find the new current image.
|
||||||
for (var i = 0; i < this.images_.length; ++i) {
|
this.currentImage_ = this.findImage_(function(image) {
|
||||||
var image = this.images_[i];
|
return image.tags.indexOf(tagName) >= 0;
|
||||||
if (image.tags.indexOf(tagName) >= 0) {
|
});
|
||||||
this.currentImage_ = image;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the state of each node.
|
// Update the state of each node.
|
||||||
var imageByDBID = this.imageByDBID_;
|
var imageByDBID = this.imageByDBID_;
|
||||||
var currentAncestors = this.getAncestors(this.currentImage_);
|
var currentAncestors = this.getAncestors_(this.currentImage_);
|
||||||
for (var i = 0; i < this.images_.length; ++i) {
|
for (var i = 0; i < this.images_.length; ++i) {
|
||||||
var image = this.images_[i];
|
var image = this.images_[i];
|
||||||
var imageNode = this.imageByDBID_[image.dbid];
|
var imageNode = this.imageByDBID_[image.dbid];
|
||||||
|
@ -219,7 +274,7 @@ ImageHistoryTree.prototype.setTag_ = function(tagName) {
|
||||||
for (var i = 0; i < this.images_.length; ++i) {
|
for (var i = 0; i < this.images_.length; ++i) {
|
||||||
var image = this.images_[i];
|
var image = this.images_[i];
|
||||||
var imageNode = this.imageByDBID_[image.dbid];
|
var imageNode = this.imageByDBID_[image.dbid];
|
||||||
var ancestors = this.getAncestors(image);
|
var ancestors = this.getAncestors_(image);
|
||||||
var immediateParent = ancestors[ancestors.length - 1] * 1;
|
var immediateParent = ancestors[ancestors.length - 1] * 1;
|
||||||
var parent = imageByDBID[immediateParent];
|
var parent = imageByDBID[immediateParent];
|
||||||
if (parent && imageNode.highlighted) {
|
if (parent && imageNode.highlighted) {
|
||||||
|
@ -236,7 +291,24 @@ ImageHistoryTree.prototype.setTag_ = function(tagName) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, update the tree.
|
this.update_(this.root_);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the current image highlighted in the tree.
|
||||||
|
*/
|
||||||
|
ImageHistoryTree.prototype.setImage_ = function(imageId) {
|
||||||
|
// Find the new current image.
|
||||||
|
var newImage = this.findImage_(function(image) {
|
||||||
|
return image.id == imageId;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (newImage == this.currentImage_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.currentImage_ = newImage;
|
||||||
this.update_(this.root_);
|
this.update_(this.root_);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -300,7 +372,7 @@ ImageHistoryTree.prototype.update_ = function(source) {
|
||||||
.attr("dy", ".35em")
|
.attr("dy", ".35em")
|
||||||
.attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; })
|
.attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; })
|
||||||
.text(function(d) { return d.name; })
|
.text(function(d) { return d.name; })
|
||||||
.on("click", function(d) { that.toggle_(d); that.update_(d); })
|
.on("click", function(d) { that.changeImage_(d.image.id); })
|
||||||
.on('mouseover', tip.show)
|
.on('mouseover', tip.show)
|
||||||
.on('mouseout', tip.hide);
|
.on('mouseout', tip.hide);
|
||||||
|
|
||||||
|
@ -345,6 +417,12 @@ ImageHistoryTree.prototype.update_ = function(source) {
|
||||||
return d._children ? "lightsteelblue" : "#fff";
|
return d._children ? "lightsteelblue" : "#fff";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Update the repo text.
|
||||||
|
nodeUpdate.select("text")
|
||||||
|
.attr("class", function(d) {
|
||||||
|
return d.image.id == that.currentImage_.id ? 'current' : '';
|
||||||
|
});
|
||||||
|
|
||||||
// Ensure that the node is visible.
|
// Ensure that the node is visible.
|
||||||
nodeUpdate.select("g")
|
nodeUpdate.select("g")
|
||||||
.style("fill-opacity", 1);
|
.style("fill-opacity", 1);
|
||||||
|
@ -369,7 +447,7 @@ ImageHistoryTree.prototype.update_ = function(source) {
|
||||||
.on("click", function(d, e) {
|
.on("click", function(d, e) {
|
||||||
var tag = this.getAttribute('data-tag');
|
var tag = this.getAttribute('data-tag');
|
||||||
if (tag) {
|
if (tag) {
|
||||||
that.setTag_(tag);
|
that.changeTag_(tag);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -55,48 +55,71 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="repo-content" ng-show="currentTag.image">
|
<div class="repo-content" ng-show="currentTag.image">
|
||||||
<!-- Tab bar -->
|
<!-- Image History -->
|
||||||
<ul class="nav nav-tabs">
|
<div id="image-history">
|
||||||
<li>
|
|
||||||
<span class="tag-dropdown dropdown" title="Tags">
|
|
||||||
<i class="icon-bookmark"><span class="tag-count">{{getTagCount(repo)}}</span></i>
|
|
||||||
<a href="javascript:void(0)" class="dropdown-toggle" data-toggle="dropdown">{{currentTag.name}} <b class="caret"></b></a>
|
|
||||||
<ul class="dropdown-menu">
|
|
||||||
<li ng-repeat="tag in repo.tags">
|
|
||||||
<a href="{{ '#/repository/' + repo.namespace + '/' + repo.name + '/tag/' + tag.name }}">{{tag.name}}</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li id="current-image-tab" class="active" ng-click="showTab('current-image')">
|
|
||||||
<a href="javascript:void(0)">Current Image</a>
|
|
||||||
</li>
|
|
||||||
<li id="image-history-tab" ng-click="showTab('image-history')">
|
|
||||||
<a href="javascript:void(0)">Image History</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<div id="current-image">
|
|
||||||
<dl class="dl-horizontal">
|
|
||||||
<dt>Created</dt>
|
|
||||||
<dd am-time-ago="parseDate(currentTag.image.created)"></dd>
|
|
||||||
<dt>ID</dt>
|
|
||||||
<dd>{{ currentTag.image.id }}</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<div ng-show="currentTag.image.comment">
|
|
||||||
<strong>Description:</strong>
|
|
||||||
<blockquote style="margin-top: 10px;" ng-bind-html-unsafe="getMarkedDown(currentTag.image.comment)">
|
|
||||||
</blockquote>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="image-history" style="display: none">
|
|
||||||
<div ng-hide="imageHistory">
|
<div ng-hide="imageHistory">
|
||||||
<i class="icon-spinner icon-spin icon-3x"></i>
|
<i class="icon-spinner icon-spin icon-3x"></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="image-history-container">
|
<div class="row">
|
||||||
|
<!-- Tree View container -->
|
||||||
|
<div class="col-md-8">
|
||||||
|
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<!-- Tag dropdown -->
|
||||||
|
<span class="tag-dropdown dropdown" title="Tags">
|
||||||
|
<i class="icon-tag"><span class="tag-count">{{getTagCount(repo)}}</span></i>
|
||||||
|
<a href="javascript:void(0)" class="dropdown-toggle" data-toggle="dropdown">{{currentTag.name}} <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li ng-repeat="tag in repo.tags">
|
||||||
|
<a href="javascript:void(0)" ng-click="setTag(tag.name)">{{tag.name}}</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</span>
|
||||||
|
<span class="right-title">Tags</span>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Tree View itself -->
|
||||||
|
<div id="image-history-container"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Side Panel -->
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<!-- Image dropdown -->
|
||||||
|
<span class="tag-dropdown dropdown" title="Images">
|
||||||
|
<i class="icon-archive"><span class="tag-count">{{imageHistory.length}}</span></i>
|
||||||
|
<a href="javascript:void(0)" class="dropdown-toggle" data-toggle="dropdown">{{currentImage.id.substr(0, 12)}} <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li ng-repeat="image in imageHistory">
|
||||||
|
<a href="javascript:void(0)" ng-click="setImage(image)">{{image.id.substr(0, 12)}}</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</span>
|
||||||
|
<span class="right-title">Images</span>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel-body">
|
||||||
|
<div id="current-image">
|
||||||
|
<dl class="dl-horizontal">
|
||||||
|
<dt>Created</dt>
|
||||||
|
<dd am-time-ago="parseDate(currentTag.image.created)"></dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<div ng-show="currentTag.image.comment">
|
||||||
|
<strong>Description:</strong>
|
||||||
|
<blockquote style="margin-top: 10px;" ng-bind-html-unsafe="getMarkedDown(currentTag.image.comment)">
|
||||||
|
</blockquote>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Reference in a new issue