mirror of
https://github.com/goharbor/harbor.git
synced 2024-12-24 17:47:46 +01:00
updates for replication and destination UI.
This commit is contained in:
parent
bd0ef1eb3d
commit
ea43ff7c28
34
controllers/ng/navigationdetail.go
Normal file
34
controllers/ng/navigationdetail.go
Normal file
@ -0,0 +1,34 @@
|
||||
package ng
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/vmware/harbor/dao"
|
||||
"github.com/vmware/harbor/models"
|
||||
"github.com/vmware/harbor/utils/log"
|
||||
)
|
||||
|
||||
type NavigationDetailController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
func (ndc *NavigationDetailController) Get() {
|
||||
sessionUserID := ndc.GetSession("userId")
|
||||
var isAdmin int
|
||||
if sessionUserID != nil {
|
||||
userID := sessionUserID.(int)
|
||||
u, err := dao.GetUser(models.User{UserID: userID})
|
||||
if err != nil {
|
||||
log.Errorf("Error occurred in GetUser, error: %v", err)
|
||||
ndc.CustomAbort(http.StatusInternalServerError, "Internal error.")
|
||||
}
|
||||
if u == nil {
|
||||
log.Warningf("User was deleted already, user id: %d, canceling request.", userID)
|
||||
ndc.CustomAbort(http.StatusUnauthorized, "")
|
||||
}
|
||||
isAdmin = u.HasAdminRole
|
||||
}
|
||||
ndc.Data["IsAdmin"] = isAdmin
|
||||
ndc.TplName = "ng/navigation-detail.htm"
|
||||
ndc.Render()
|
||||
}
|
17
static/ng/resources/css/admin-options.css
Normal file
17
static/ng/resources/css/admin-options.css
Normal file
@ -0,0 +1,17 @@
|
||||
.switch-pane-admin-options {
|
||||
display: inline;
|
||||
width: 345px;
|
||||
float: right;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.switch-pane-admin-options a, .switch-pane-admin-options span {
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.switch-pane-admin-options li .active {
|
||||
border-bottom: 2px solid rgb(0, 84, 190);
|
||||
font-weight: bold;
|
||||
}
|
3
static/ng/resources/css/destination.css
Normal file
3
static/ng/resources/css/destination.css
Normal file
@ -0,0 +1,3 @@
|
||||
.create-destination {
|
||||
height: 235px;
|
||||
}
|
67
static/ng/resources/css/replication.css
Normal file
67
static/ng/resources/css/replication.css
Normal file
@ -0,0 +1,67 @@
|
||||
.create-policy {
|
||||
height: 535px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.form-group-custom {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.h4-custom {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.h4-custom-down {
|
||||
display: inline-block;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.hr-line {
|
||||
margin-top: 0;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.form-control-custom {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.pane-split {
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#upon-pane {
|
||||
margin-top: 10px;
|
||||
height: 270px;
|
||||
min-height: 100px;
|
||||
max-height: 270px;
|
||||
}
|
||||
|
||||
#upon-pane table>tbody>tr {
|
||||
cursor: all-scroll;
|
||||
}
|
||||
#down-pane {
|
||||
height: 80px;
|
||||
min-height: 80px;
|
||||
}
|
||||
|
||||
.sub-pane-split {
|
||||
margin: 15px;
|
||||
height: auto;
|
||||
min-height: 50px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.well-split {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.split-handle {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
cursor: ns-resize;
|
||||
color: #C0C0C0;
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
<div class="modal fade" id="createPolicyModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<form name="form" class="form-horizontal css-form" novalidate>
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title"><span class="glyphicon glyphicon-plus"></span> Create New Policy</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="create-policy">
|
||||
<div class="col-md-12">
|
||||
<h4>General</h4>
|
||||
<hr class="hr-line"/>
|
||||
</div>
|
||||
<div class="form-group col-md-12 form-group-custom">
|
||||
<label for="name" class="col-md-3 control-label">Name:</label>
|
||||
<div class="col-md-9">
|
||||
<input type="text" class="form-control form-control-custom" id="name" ng-model="replication.policy.name" ng-model-options="{ debounce: 500 }" name="uName" required>
|
||||
<div ng-messages="form.$submitted && form.uName.$error">
|
||||
<span ng-message="required">Name is required.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-12 form-group-custom">
|
||||
<label for="description" class="col-md-3 control-label">Description:</label>
|
||||
<div class="col-md-9">
|
||||
<textarea class="form-control form-control-custom" id="description" ng-model="replication.policy.description" ng-model-options="{ updateOn: 'blur' }" ng-value="description" name="uDescription" required ></textarea>
|
||||
<div ng-messages="form.$submitted && form.uDescription.$error">
|
||||
<span ng-message="required">Description is required.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-12 form-group-custom">
|
||||
<label for="enable" class="col-md-3 control-label">Enable:</label>
|
||||
<div class="col-md-9">
|
||||
<input type="checkbox" class="form-control" style="margin-top: 10px; height: auto;" ng-model="replication.policy.enabled" ng-model-options="{ updateOn: 'blur' }" ng-checked="enabled">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<h4 class="h4-custom">Destination Setting</h4>
|
||||
<hr class="hr-line"/>
|
||||
</div>
|
||||
<div class="form-group col-md-12 form-group-custom">
|
||||
<label for="destinationName" class="col-md-3 control-label">Name:</label>
|
||||
<div class="col-md-7">
|
||||
<select class="form-control form-control-custom" id="destinationName" ng-model="replication.destinations" ng-options="d as d.name for d in vm.destinations track by d.id" ng-click="vm.selectDestination()"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-12 form-group-custom">
|
||||
<label for="endpoint" class="col-md-3 control-label">Endpoint:</label>
|
||||
<div class="col-md-9">
|
||||
<input type="text" class="form-control form-control-custom" id="endpoint" ng-model="replication.destination.endpoint" ng-model-options="{ updateOn: 'blur' }" ng-value="endpoint" name="uEndpoint" required>
|
||||
<div ng-messages="form.$submitted && form.uEndpoint.$error">
|
||||
<span ng-message="required">Endpoint is required.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-12 form-group-custom">
|
||||
<label for="username" class="col-md-3 control-label">Username:</label>
|
||||
<div class="col-md-9">
|
||||
<input type="text" class="form-control" id="username" ng-model="replication.destination.username" ng-model-options="{ updateOn: 'blur' }" ng-value="username" name="uUsername" required>
|
||||
<div ng-messages="form.$submitted && form.uUsername.$error">
|
||||
<span ng-message="required">Username is required.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-12 form-group-custom">
|
||||
<label for="password" class="col-md-3 control-label">Password:</label>
|
||||
<div class="col-md-9">
|
||||
<input type="password" class="form-control" id="password" ng-model="replication.destination.password" ng-model-options="{ updateOn: 'blur' }" ng-value="password" name="uPassword" required>
|
||||
<div ng-messages="form.$submitted && form.uPassword.$error">
|
||||
<span ng-message="required">Password is required.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-12 form-group-custom">
|
||||
<div class="col-md-3"></div>
|
||||
<div class="col-md-9">
|
||||
<button class="btn btn-default" ng-click="vm.testConnection()">Test Connection</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-primary" id="btnOk">// 'ok' | tr //</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">// 'close' | tr //</button>
|
||||
</div>
|
||||
</form>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
@ -0,0 +1,32 @@
|
||||
(function() {
|
||||
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('harbor.replication')
|
||||
.directive('createPolicy', createPolicy);
|
||||
|
||||
function CreatePolicyController() {
|
||||
var vm = this;
|
||||
vm.enabled = true;
|
||||
vm.save = save;
|
||||
|
||||
function save(policy) {
|
||||
console.log(angular.toJson(policy));
|
||||
}
|
||||
}
|
||||
|
||||
function createPolicy() {
|
||||
var directive = {
|
||||
'restrict': 'E',
|
||||
'templateUrl': '/static/ng/resources/js/components/replication/create-policy.directive.html',
|
||||
'scope': true,
|
||||
'replace': true,
|
||||
'controller': CreatePolicyController,
|
||||
'controllerAs': 'vm',
|
||||
'bindToController': true
|
||||
};
|
||||
return directive;
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,79 @@
|
||||
<div class="tab-pane">
|
||||
<div class="col-xs-12 col-md-12 each-tab-pane">
|
||||
<div class="form-inline">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" placeholder="" ng-model="vm.replicationName" size="30">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-primary" type="button" ng-click="vm.search()"><span class="glyphicon glyphicon-search"></span></button>
|
||||
</span>
|
||||
</div>
|
||||
<button ng-if="!vm.isOpen" class="btn btn-success" type="button" ng-click="vm.addReplication()" data-toggle="modal" data-target="#createPolicyModal"><span class="glyphicon glyphicon-plus"></span>New Replication</button>
|
||||
<create-policy></create-policy>
|
||||
</div>
|
||||
<div class="pane-split" id="upon-pane">
|
||||
<div class="sub-pane-split">
|
||||
<table class="table table-pane">
|
||||
<thead>
|
||||
<th width="10%">Name</th>
|
||||
<th width="18%">Description</th>
|
||||
<th width="14%">Destination</th>
|
||||
<th width="18%">Start Time</th>
|
||||
<th width="14%">Status</th>
|
||||
<th width="14%">Activation</th>
|
||||
<th width="12%">Actions</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-if="vm.replicationPolicies.length == 0">
|
||||
<td colspan="7" height="100%" class="empty-hint" ><h3 class="text-muted">No replication policies, add new replication policy.</h3></td>
|
||||
</tr>
|
||||
<tr policy_id="//r.policy_id//" ng-if="vm.replicationPolicies.length > 0" ng-repeat="r in vm.replicationPolicies" value="//vm.last = $last//">
|
||||
<td>//r.name//</td>
|
||||
<td>//r.description//</td>
|
||||
<td>//r.destination//</td>
|
||||
<td>//r.start_time//</td>
|
||||
<td>//r.status//</td>
|
||||
<td>//r.activation//</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-4 col-md-12 well well-sm well-custom well-split"><div class="col-md-offset-10">//vm.projects ? vm.projects.length : 0// // 'items' | tr //</div></div>
|
||||
<p class="split-handle"><span class="glyphicon glyphicon-align-justify"></span></p>
|
||||
<h4 class="h4-custom-down">Replication Jobs</h4>
|
||||
<hr class="hr-line"/>
|
||||
<div class="form-inline">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" placeholder="" ng-model="vm.replicationJobnName" size="30">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-primary" type="button" ng-click="vm.search()"><span class="glyphicon glyphicon-search"></span></button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pane-split" id="down-pane">
|
||||
<div class="sub-pane-split">
|
||||
<table class="table table-pane" width="98%">
|
||||
<thead>
|
||||
<th width="20%">Name</th>
|
||||
<th width="25%">Operation</th>
|
||||
<th width="40%">Start Time</th>
|
||||
<th width="15%">Status</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-if="vm.replicationJobs.length == 0">
|
||||
<td colspan="4" height="100%" class="empty-hint" ><h3 class="text-muted">No replication jobs.</h3></td>
|
||||
</tr>
|
||||
<tr ng-if="vm.replicationJobs.length > 0" ng-repeat="r in vm.replicationJobs">
|
||||
<td>//r.name//</td>
|
||||
<td>//r.operation//</td>
|
||||
<td>//r.start_time//</td>
|
||||
<td>//r.status//</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,119 @@
|
||||
(function() {
|
||||
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('harbor.replication')
|
||||
.directive('listReplication', listReplication);
|
||||
|
||||
ListReplicationController.$inject = ['getParameterByName', '$location', 'ListReplicationPolicyService', 'ListReplicationJobService'];
|
||||
|
||||
function ListReplicationController(getParameterByName, $location, ListReplicationPolicyService, ListReplicationJobService) {
|
||||
var vm = this;
|
||||
|
||||
vm.projectId = getParameterByName('project_id', $location.absUrl());
|
||||
|
||||
vm.addReplication = addReplication;
|
||||
vm.retrievePolicy = retrievePolicy;
|
||||
vm.retrieveJob = retrieveJob;
|
||||
vm.last = false;
|
||||
|
||||
vm.retrievePolicy();
|
||||
|
||||
function retrievePolicy() {
|
||||
ListReplicationPolicyService(vm.projectId, vm.replicationName)
|
||||
.success(listReplicationPolicySuccess)
|
||||
.error(listReplicationPolicyFailed);
|
||||
}
|
||||
|
||||
function retrieveJob(policyId) {
|
||||
ListReplicationJobService(policyId, vm.replicationJobName)
|
||||
.success(listReplicationJobSuccess)
|
||||
.error(listReplicationJobFailed);
|
||||
}
|
||||
|
||||
function listReplicationPolicySuccess(data, status) {
|
||||
vm.replicationPolicies = data || [];
|
||||
}
|
||||
|
||||
function listReplicationPolicyFailed(data, status) {
|
||||
console.log('Failed list replication policy:' + data);
|
||||
}
|
||||
|
||||
function listReplicationJobSuccess(data, status) {
|
||||
vm.replicationJobs = data || [];
|
||||
}
|
||||
|
||||
function listReplicationJobFailed(data, status) {
|
||||
console.log('Failed list replication job:' + data);
|
||||
}
|
||||
|
||||
function addReplication() {
|
||||
vm.modalTitle = 'Create New Policy';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function listReplication($timeout) {
|
||||
var directive = {
|
||||
'restrict': 'E',
|
||||
'templateUrl': '/static/ng/resources/js/components/replication/list-replication.directive.html',
|
||||
'scope': true,
|
||||
'link': link,
|
||||
'controller': ListReplicationController,
|
||||
'controllerAs': 'vm',
|
||||
'bindToController': true
|
||||
};
|
||||
return directive;
|
||||
|
||||
function link(scope, element, attrs, ctrl) {
|
||||
var uponPaneHeight = element.find('#upon-pane').height();
|
||||
var handleHeight = element.find('.split-handle').height() + element.find('.split-handle').offset().top + element.find('.well').height() - 24;
|
||||
|
||||
var maxDownPaneHeight = 245;
|
||||
|
||||
element.find('.split-handle').on('mousedown', mousedownHandler);
|
||||
|
||||
function mousedownHandler(e) {
|
||||
e.preventDefault();
|
||||
$(document).on('mousemove', mousemoveHandler);
|
||||
$(document).on('mouseup', mouseupHandler);
|
||||
}
|
||||
|
||||
function mousemoveHandler(e) {
|
||||
if(element.find('#down-pane').height() <= maxDownPaneHeight) {
|
||||
element.find('#upon-pane').css({'height' : (uponPaneHeight - (handleHeight - e.pageY)) + 'px'});
|
||||
element.find('#down-pane').css({'height' : (uponPaneHeight + (handleHeight - e.pageY - 196)) + 'px'});
|
||||
}else{
|
||||
element.find('#down-pane').css({'height' : (maxDownPaneHeight) + 'px'});
|
||||
$(document).off('mousemove');
|
||||
}
|
||||
}
|
||||
function mouseupHandler(e) {
|
||||
$(document).off('mousedown');
|
||||
$(document).off('mousemove');
|
||||
}
|
||||
|
||||
scope.$watch('vm.last', function(current) {
|
||||
$timeout(function(){
|
||||
if(current) {
|
||||
element.find('#upon-pane table>tbody>tr').on('click', trClickHandler);
|
||||
element.find('#upon-pane table>tbody>tr:eq(0)').trigger('click');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function trClickHandler(e) {
|
||||
element
|
||||
.find('#upon-pane table>tbody>tr')
|
||||
.css({'background-color': '#FFFFFF'})
|
||||
.css({'color': '#000'});
|
||||
$(this)
|
||||
.css({'background-color': '#057ac9'})
|
||||
.css({'color': '#fff'});
|
||||
ctrl.retrieveJob($(this).attr('policy_id'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,11 @@
|
||||
(function() {
|
||||
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('harbor.replication', [
|
||||
'harbor.services.replication.policy',
|
||||
'harbor.services.replication.job'
|
||||
]);
|
||||
|
||||
})();
|
@ -0,0 +1,62 @@
|
||||
<form name="form" class="form-horizontal" ng-submit="form.$valid && vm.changeSettings(system)" >
|
||||
<div class="col-md-12">
|
||||
<h5>System Settings</h5>
|
||||
<hr/>
|
||||
</div>
|
||||
<div class="col-md-12 col-md-off-set-1 main-content">
|
||||
<div class="form-group">
|
||||
<label for="hostName" class="col-sm-3 control-label">Host Name:</label>
|
||||
<div class="col-sm-7">
|
||||
<input type="text" class="form-control" id="hostName" ng-model="system.hostName" ng-model-options="{ updateOn: 'blur' }" ng-value="vm.system.hostName" name="uHostName" required>
|
||||
<div ng-messages="form.$dirty && form.uHostName.$error">
|
||||
<span ng-message="required">Host name is required.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="urlProtocol" class="col-sm-3 control-label">URL Protocol:</label>
|
||||
<div class="col-sm-7">
|
||||
<input type="text" class="form-control" id="urlProtocol" ng-model="system.urlProtocol" ng-model-options="{ updateOn: 'blur' }" ng-value="vm.system.urlProtocol" name="uUrlProtocol" required>
|
||||
<div ng-messages="form.$dirty && form.uUrlProtocol.$error">
|
||||
<span ng-message="required">Url protocol is required.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="emailServer" class="col-sm-3 control-label">Email server:</label>
|
||||
<div class="col-sm-7">
|
||||
<input type="text" class="form-control" id="emailServer" ng-model="system.emailServer" ng-model-options="{ updateOn: 'blur' }" ng-value="vm.system.emailServer" name="uEmailServer" required>
|
||||
<div ng-messages="form.$dirty && form.uEmailServer.$error">
|
||||
<span ng-message="required">Email server is required.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="ldapUrl" class="col-sm-3 control-label">LDAP URL:</label>
|
||||
<div class="col-sm-7">
|
||||
<input type="text" class="form-control" id="ldapUrl" ng-model="system.ldapUrl" ng-model-options="{ updateOn: 'blur' }" ng-value="vm.system.ldapUrl" name="uLdapUrl" required>
|
||||
<div ng-messages="form.$dirty && form.uLdapUrl.$error">
|
||||
<span ng-message="required">LDAP URL is required.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<h5>Registration</h5>
|
||||
<hr/>
|
||||
</div>
|
||||
<div class="col-md-12 col-md-off-set-1 main-content">
|
||||
<div class="form-group">
|
||||
<label for="registration" class="col-sm-3 control-label">Registration:</label>
|
||||
<div class="col-sm-7">
|
||||
<select class="form-control" ng-model="vm.currentRegistration" ng-options="r as r.name for r in vm.registrationOptions track by r.value" ng-click="vm.selectRegistration()"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-md-offset-7 col-md-10">
|
||||
<input type="submit" class="btn btn-primary" ng-disabled="form.$invalid" value="Save">
|
||||
<input type="submit" class="btn btn-default" ng-click="vm.cancel()" value="Cancel">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
@ -0,0 +1,54 @@
|
||||
(function() {
|
||||
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('harbor.system.management')
|
||||
.directive('configuration', configuration);
|
||||
|
||||
ConfigurationController.$inject = [];
|
||||
|
||||
function ConfigurationController() {
|
||||
var vm = this;
|
||||
|
||||
vm.registrationOptions = [
|
||||
{
|
||||
'name': 'on',
|
||||
'value': true
|
||||
},
|
||||
{
|
||||
'name': 'off',
|
||||
'value': false
|
||||
}
|
||||
];
|
||||
vm.currentRegistration = {
|
||||
'name': 'on',
|
||||
'value': true
|
||||
};
|
||||
|
||||
vm.changeSettings = changeSettings;
|
||||
|
||||
vm.selectRegistration = selectRegistration;
|
||||
|
||||
function selectRegistration() {
|
||||
|
||||
}
|
||||
|
||||
function changeSettings(system) {
|
||||
console.log(system);
|
||||
}
|
||||
}
|
||||
|
||||
function configuration() {
|
||||
var directive = {
|
||||
'restrict': 'E',
|
||||
'templateUrl': '/static/ng/resources/js/components/system-management/configuration.directive.html',
|
||||
'scope': true,
|
||||
'controller': ConfigurationController,
|
||||
'controllerAs': 'vm',
|
||||
'bindToController': true
|
||||
};
|
||||
return directive;
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,62 @@
|
||||
<div class="modal fade" id="createDestinationModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title"><span class="glyphicon glyphicon-plus"></span> Create New Destination</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="create-destination">
|
||||
<form name="form" class="form-horizontal" ng-submit="form.$valid" novalidate>
|
||||
<div class="form-group col-md-12 form-group-custom">
|
||||
<label for="name" class="col-md-3 control-label">Name:</label>
|
||||
<div class="col-md-9">
|
||||
<input type="text" class="form-control form-control-custom" id="name" ng-model="destination.name" ng-model-options="{ updateOn: 'blur' }" ng-value="vm.destination.name" name="uName" required>
|
||||
<div ng-messages="form.$dirty && form.uName.$error">
|
||||
<span ng-message="required">Name is required.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-12 form-group-custom">
|
||||
<label for="description" class="col-md-3 control-label">Endpoint:</label>
|
||||
<div class="col-md-9">
|
||||
<input type="text" class="form-control form-control-custom" id="endpoint" ng-model="destination.endpoint" ng-model-options="{ updateOn: 'blur' }" ng-value="vm.destination.endpoint" name="uEndpoint" required >
|
||||
<div ng-messages="form.$dirty && form.uEndpoint.$error">
|
||||
<span ng-message="required">Endpoint is required.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-12 form-group-custom">
|
||||
<label for="username" class="col-md-3 control-label">Username:</label>
|
||||
<div class="col-md-9">
|
||||
<input type="text" class="form-control" id="username" ng-model="destination.username" ng-model-options="{ updateOn: 'blur' }" ng-value="vm.destination.username" name="uUsername" required>
|
||||
<div ng-messages="form.$dirty && form.uUsername.$error">
|
||||
<span ng-message="required">Username is required.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-12 form-group-custom">
|
||||
<label for="password" class="col-md-3 control-label">Password:</label>
|
||||
<div class="col-md-9">
|
||||
<input type="password" class="form-control" id="password" ng-model="destination.password" ng-model-options="{ updateOn: 'blur' }" ng-value="vm.destination.password" name="uPassword" required>
|
||||
<div ng-messages="form.$dirty && form.uPassword.$error">
|
||||
<span ng-message="required">Password is required.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-12 form-group-custom">
|
||||
<div class="col-md-3"></div>
|
||||
<div class="col-md-9">
|
||||
<button class="btn btn-default" ng-click="vm.testConnection()">Test Connection</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" id="btnOk" ng-click="vm.save(destination)">// 'ok' | tr //</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">// 'close' | tr //</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
@ -0,0 +1,47 @@
|
||||
(function() {
|
||||
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('harbor.system.management')
|
||||
.directive('createDestination', createDestination);
|
||||
|
||||
CreateDestinationController.$inject = ['CreateDestinationService'];
|
||||
|
||||
function CreateDestinationController(CreateDestinationService) {
|
||||
var vm = this;
|
||||
vm.save = save;
|
||||
|
||||
function save(destination) {
|
||||
if(destination) {
|
||||
console.log('destination:' + angular.toJson(destination));
|
||||
CreateDestinationService(destination.name, destination.endpoint,
|
||||
destination.username, destination.password)
|
||||
.success(createDestinationSuccess)
|
||||
.error(createDestinationFailed);
|
||||
}
|
||||
}
|
||||
|
||||
function createDestinationSuccess(data, status) {
|
||||
alert('Successful created destination.');
|
||||
}
|
||||
|
||||
function createDestinationFailed(data, status) {
|
||||
console.log('Failed create destination:' + data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function createDestination() {
|
||||
var directive = {
|
||||
'restrict': 'E',
|
||||
'templateUrl': '/static/ng/resources/js/components/system-management/create-destination.directive.html',
|
||||
'scope': true,
|
||||
'controller': CreateDestinationController,
|
||||
'controllerAs': 'vm',
|
||||
'bindToController': true
|
||||
};
|
||||
return directive;
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,38 @@
|
||||
<div class="tab-pane">
|
||||
<div class="col-xs-12 col-md-12 each-tab-pane">
|
||||
<div class="form-inline">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" placeholder="" ng-model="vm.destinationName" size="30">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-primary" type="button" ng-click="vm.search()"><span class="glyphicon glyphicon-search"></span></button>
|
||||
</span>
|
||||
</div>
|
||||
<button ng-if="!vm.isOpen" class="btn btn-success" type="button" ng-click="vm.addDestination()" data-toggle="modal" data-target="#createDestinationModal"><span class="glyphicon glyphicon-plus"></span>New Destination</button>
|
||||
<create-destination></create-destination>
|
||||
</div>
|
||||
<div class="pane">
|
||||
<div class="sub-pane">
|
||||
<table class="table table-pane">
|
||||
<thead>
|
||||
<th width="20%">Name</th>
|
||||
<th width="40%">Endpoint</th>
|
||||
<th width="20%">Creation Time</th>
|
||||
<th width="20%">Action</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-if="vm.destinations.length == 0">
|
||||
<td colspan="7" height="100%" class="empty-hint" ><h3 class="text-muted">No destinations, add new destination.</h3></td>
|
||||
</tr>
|
||||
<tr ng-if="vm.destinations.length > 0" ng-repeat="r in vm.destinations">
|
||||
<td>//r.name//</td>
|
||||
<td>//r.url//</td>
|
||||
<td>//r.creation_time//</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-4 col-md-12 well well-sm well-custom well-split"><div class="col-md-offset-10">//vm.destinations ? vm.destinations.length : 0// // 'items' | tr //</div></div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,51 @@
|
||||
(function() {
|
||||
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('harbor.system.management')
|
||||
.directive('destination', destination);
|
||||
|
||||
DestinationController.$inject = ['ListDestinationService'];
|
||||
|
||||
function DestinationController(ListDestinationService) {
|
||||
var vm = this;
|
||||
|
||||
vm.retrieve = retrieve;
|
||||
vm.search = search;
|
||||
vm.retrieve();
|
||||
|
||||
function retrieve() {
|
||||
ListDestinationService()
|
||||
.success(listDestinationSuccess)
|
||||
.error(listDestinationFailed);
|
||||
}
|
||||
|
||||
function search() {
|
||||
vm.retrieve();
|
||||
}
|
||||
|
||||
function listDestinationSuccess(data, status) {
|
||||
vm.destinations = data;
|
||||
}
|
||||
|
||||
function listDestinationFailed(data, status) {
|
||||
console.log('Failed list destination:' + data);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
function destination() {
|
||||
var directive = {
|
||||
'restrict': 'E',
|
||||
'templateUrl': '/static/ng/resources/js/components/system-management/destination.directive.html',
|
||||
'scope': true,
|
||||
'controller': DestinationController,
|
||||
'controllerAs': 'vm',
|
||||
'bindToController': true
|
||||
};
|
||||
return directive;
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,44 @@
|
||||
<div class="tab-pane">
|
||||
<div class="col-xs-12 col-md-12 each-tab-pane">
|
||||
<div class="form-inline">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" placeholder="" ng-model="vm.replicationName" size="30">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-primary" type="button" ng-click="vm.search()"><span class="glyphicon glyphicon-search"></span></button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pane">
|
||||
<div class="sub-pane">
|
||||
<table class="table table-pane">
|
||||
<thead>
|
||||
<th width="12%">Name</th>
|
||||
<th width="14%">Description</th>
|
||||
<th width="12%">Project</th>
|
||||
<th width="14%">Destination</th>
|
||||
<th width="12%">Start Time</th>
|
||||
<th width="12%">Status</th>
|
||||
<th width="12%">Activation</th>
|
||||
<th width="12%">Actions</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-if="vm.replications.length == 0">
|
||||
<td colspan="7" height="100%" class="empty-hint" ><h3 class="text-muted">No replications.</h3></td>
|
||||
</tr>
|
||||
<tr ng-if="vm.replications.length > 0" ng-repeat="r in vm.replications">
|
||||
<td>//r.name//</td>
|
||||
<td>//r.description//</td>
|
||||
<td>//r.project//</td>
|
||||
<td>//r.destination//</td>
|
||||
<td>//r.start_time//</td>
|
||||
<td>//r.status//</td>
|
||||
<td>//r.activation//</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-4 col-md-12 well well-sm well-custom well-split"><div class="col-md-offset-10">//vm.replications ? vm.replications.length : 0// // 'items' | tr //</div></div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,33 @@
|
||||
(function() {
|
||||
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('harbor.system.management')
|
||||
.directive('replication', replication);
|
||||
|
||||
ReplicationController.$inject = ['ListReplicationPolicyService'];
|
||||
|
||||
function ReplicationController(ListReplicationPolicyService) {
|
||||
var vm = this;
|
||||
ListReplicationPolicyService()
|
||||
.then(function(data) {
|
||||
vm.replications = data;
|
||||
}, function(data) {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function replication() {
|
||||
var directive = {
|
||||
'restrict': 'E',
|
||||
'templateUrl': '/static/ng/resources/js/components/system-management/replication.directive.html',
|
||||
'scope': true,
|
||||
'controller': ReplicationController,
|
||||
'controllerAs': 'vm',
|
||||
'bindToController': true
|
||||
};
|
||||
return directive;
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,10 @@
|
||||
<div class="switch-pane">
|
||||
<span>
|
||||
<navigation-admin-options target="vm.target"></navigation-admin-options>
|
||||
</span>
|
||||
</div>
|
||||
<div class="pane project-pane">
|
||||
<destination ng-if="vm.target === 'destinations'"></destination>
|
||||
<replication ng-if="vm.target === 'replication'"></replication>
|
||||
<configuration ng-if="vm.target === 'configuration'"></configuration>
|
||||
</div>
|
@ -0,0 +1,26 @@
|
||||
(function() {
|
||||
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('harbor.system.management')
|
||||
.directive('systemManagement', systemManagement);
|
||||
|
||||
function SystemManagementController() {
|
||||
var vm = this;
|
||||
vm.target = 'destinations';
|
||||
}
|
||||
|
||||
function systemManagement() {
|
||||
var directive = {
|
||||
'restrict': 'E',
|
||||
'templateUrl': '/static/ng/resources/js/components/system-management/system-management.directive.html',
|
||||
'scope': true,
|
||||
'controller': SystemManagementController,
|
||||
'controllerAs': 'vm',
|
||||
'bindToController': true
|
||||
};
|
||||
return directive;
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,8 @@
|
||||
(function() {
|
||||
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('harbor.system.management', []);
|
||||
|
||||
})();
|
@ -0,0 +1,35 @@
|
||||
<div class="search-pane">
|
||||
<div class="form-inline">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" placeholder="" ng-model="vm.username" size="30">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-primary" type="button" ng-click="vm.searchUser()"><span class="glyphicon glyphicon-search"></span></button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pane project-pane">
|
||||
<div class="sub-pane">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<th>// 'username' | tr //</th><th>// 'role' | tr //</th><th>// 'email' | tr //</th><th>// 'registration_time' | tr //</th><th>// 'operation' | tr //</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="u in vm.users">
|
||||
<td>//u.username//</td>
|
||||
<td>N/A</td>
|
||||
<td>//u.email//</td>
|
||||
<td>//u.creation_time | dateL : 'YYYY-MM-DD HH:mm:ss'//</td>
|
||||
<td>
|
||||
<toggle-admin has-admin-role="u.HasAdminRole == 1" user-id="//u.UserId//"></toggle-admin>
|
||||
<a href="javascript:void(0)" ng-click="vm.deleteUser(u.UserId)"><span class="glyphicon glyphicon-trash"></span></a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-xs-4 col-md-12 well well-sm well-custom">
|
||||
<div class="col-md-offset-10">//vm.users ? vm.users.length : 0// items</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -0,0 +1,67 @@
|
||||
(function() {
|
||||
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('harbor.user')
|
||||
.directive('listUser', listUser);
|
||||
|
||||
ListUserController.$inject = ['ListUserService', 'DeleteUserService'];
|
||||
|
||||
function ListUserController(ListUserService, DeleteUserService) {
|
||||
var vm = this;
|
||||
|
||||
vm.username = '';
|
||||
vm.searchUser = searchUser;
|
||||
vm.deleteUser = deleteUser;
|
||||
vm.retrieve = retrieve;
|
||||
|
||||
vm.retrieve();
|
||||
|
||||
function searchUser() {
|
||||
vm.retrieve();
|
||||
}
|
||||
|
||||
function deleteUser(userId) {
|
||||
DeleteUserService(userId)
|
||||
.success(deleteUserSuccess)
|
||||
.error(deleteUserFailed);
|
||||
}
|
||||
|
||||
function retrieve() {
|
||||
ListUserService(vm.username)
|
||||
.success(listUserSuccess)
|
||||
.error(listUserFailed);
|
||||
}
|
||||
|
||||
function deleteUserSuccess(data, status) {
|
||||
console.log('Successful delete user.');
|
||||
vm.retrieve();
|
||||
}
|
||||
|
||||
function deleteUserFailed(data, status) {
|
||||
console.log('Failed delete user.');
|
||||
}
|
||||
|
||||
function listUserSuccess(data, status) {
|
||||
vm.users = data;
|
||||
}
|
||||
|
||||
function listUserFailed(data, status) {
|
||||
console.log('Failed list user:' + data);
|
||||
}
|
||||
}
|
||||
|
||||
function listUser() {
|
||||
var directive = {
|
||||
'restrict': 'E',
|
||||
'templateUrl': '/static/ng/resources/js/components/user/list-user.directive.html',
|
||||
'scope': true,
|
||||
'controller': ListUserController,
|
||||
'controllerAs': 'vm',
|
||||
'bindToController': true
|
||||
};
|
||||
return directive;
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,5 @@
|
||||
<ul class="switch-pane-admin-options" role="tablist">
|
||||
<li><a tag="destinations" href="#/destinations">Destinations</a><span class="gutter">|</span></li>
|
||||
<li><a tag="replication" href="#/replication">Replication</a><span class="gutter">|</span></li>
|
||||
<li><a tag="configuration" href="#/configuration">Configuration</a></li>
|
||||
</ul>
|
@ -0,0 +1,51 @@
|
||||
(function() {
|
||||
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('harbor.layout.navigation')
|
||||
.directive('navigationAdminOptions', navigationAdminOptions);
|
||||
|
||||
NavigationAdminOptions.$inject = ['$location'];
|
||||
|
||||
function NavigationAdminOptions($location) {
|
||||
var vm = this;
|
||||
vm.path = $location.path();
|
||||
}
|
||||
|
||||
function navigationAdminOptions() {
|
||||
var directive = {
|
||||
'restrict': 'E',
|
||||
'templateUrl': '/static/ng/resources/js/layout/navigation/navigation-admin-options.directive.html',
|
||||
'scope': {
|
||||
'target': '='
|
||||
},
|
||||
'link': link,
|
||||
'controller': NavigationAdminOptions,
|
||||
'controllerAs': 'vm',
|
||||
'bindToController': true
|
||||
};
|
||||
return directive;
|
||||
|
||||
function link(scope, element, attrs, ctrl) {
|
||||
var visited = ctrl.path.substring(1);
|
||||
console.log('visited:' + visited);
|
||||
|
||||
if(visited) {
|
||||
element.find('a[tag="' + visited + '"]').addClass('active');
|
||||
}else{
|
||||
element.find('a:first').addClass('active');
|
||||
}
|
||||
|
||||
element.find('a').on('click', click);
|
||||
|
||||
function click(event) {
|
||||
element.find('a').removeClass('active');
|
||||
$(event.target).addClass('active');
|
||||
ctrl.target = $(this).attr('tag');
|
||||
scope.$apply();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,24 @@
|
||||
(function() {
|
||||
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('harbor.services.destination')
|
||||
.factory('CreateDestinationService', CreateDestinationService);
|
||||
|
||||
CreateDestinationService.$inject = ['$http'];
|
||||
|
||||
function CreateDestinationService($http) {
|
||||
return createDestination;
|
||||
function createDestination(name, endpoint, username, password) {
|
||||
return $http
|
||||
.post('/api/targets', {
|
||||
'name': name,
|
||||
'url': endpoint,
|
||||
'username': username,
|
||||
'password': password
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
})()
|
@ -0,0 +1,8 @@
|
||||
(function() {
|
||||
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('harbor.services.destination', []);
|
||||
|
||||
})();
|
@ -0,0 +1,23 @@
|
||||
(function() {
|
||||
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('harbor.services.destination')
|
||||
.factory('ListDestinationService', ListDestinationService);
|
||||
|
||||
ListDestinationService.$inject = ['$http'];
|
||||
|
||||
function ListDestinationService($http) {
|
||||
return listDestination;
|
||||
function listDestination(name) {
|
||||
return $http
|
||||
.get('/api/targets', {
|
||||
'params': {
|
||||
'name': name
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
})()
|
@ -0,0 +1,25 @@
|
||||
(function() {
|
||||
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('harbor.services.replication.job')
|
||||
.factory('ListReplicationJobService', ListReplicationJobService);
|
||||
|
||||
ListReplicationJobService.$inject = ['$http'];
|
||||
|
||||
function ListReplicationJobService($http) {
|
||||
|
||||
return listReplicationJob;
|
||||
|
||||
function listReplicationJob(policyId, name) {
|
||||
return $http
|
||||
.get('/api/jobs/replication/', {
|
||||
'params': {
|
||||
'policy_id': policyId,
|
||||
'name': name
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
})();
|
@ -0,0 +1,8 @@
|
||||
(function() {
|
||||
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('harbor.services.replication.job', []);
|
||||
|
||||
})();
|
@ -0,0 +1,28 @@
|
||||
(function() {
|
||||
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('harbor.services.replication.policy')
|
||||
.factory('CreateReplicationPolicyService', CreateReplicationPolicyService);
|
||||
|
||||
CreateReplicationPolicyService.$inject = ['$http'];
|
||||
|
||||
function CreateReplicationPolicyService($http) {
|
||||
return createReplicaitonPolicy;
|
||||
|
||||
function createReplicationPolicy(policy) {
|
||||
return $http
|
||||
.post('/api/policies/replication', {
|
||||
'project_id': policy.projectId,
|
||||
'target_id': policy.targetId,
|
||||
'name': policy.name,
|
||||
'enabled': policy.enabled,
|
||||
'description': policy.description,
|
||||
'cron_str': policy.cronStr,
|
||||
'start_time': policy.startTime
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,27 @@
|
||||
(function() {
|
||||
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('harbor.services.replication.policy')
|
||||
.factory('ListReplicationPolicyService', ListReplicationPolicyService);
|
||||
|
||||
ListReplicationPolicyService.$inject = ['$http'];
|
||||
|
||||
function ListReplicationPolicyService($http) {
|
||||
|
||||
return listReplicationPolicy;
|
||||
|
||||
function listReplicationPolicy(projectId, name) {
|
||||
return $http
|
||||
.get('/api/policies/replication', {
|
||||
'params': {
|
||||
'project_id': projectId,
|
||||
'name': name
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,8 @@
|
||||
(function() {
|
||||
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('harbor.services.replication.policy', []);
|
||||
|
||||
})();
|
24
views/ng/header.htm
Normal file
24
views/ng/header.htm
Normal file
@ -0,0 +1,24 @@
|
||||
<nav class="navbar navbar-default navbar-custom" ng-controller="HeaderController as vm">
|
||||
<div class="container container-custom">
|
||||
<!-- Brand and toggle get grouped for better mobile display -->
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-harbor-navbar-collapse-1" aria-expanded="false">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="/ng/main"><img class="img-responsive" src="/static/ng/resources/img/Harbor_Logo_rec.png" alt="Harbor's Logo"/></a>
|
||||
</div>
|
||||
<!-- Collect the nav links, forms, and other content for toggling -->
|
||||
<div class="collapse navbar-collapse" id="bs-harbor-navbar-collapse-1">
|
||||
<optional-menu current="vm.current"></optional-menu>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li>
|
||||
<navigation-header></navigation-header>
|
||||
</li>
|
||||
<li>
|
||||
<search-input search-input='vm.searchInput'></search-input>
|
||||
</li>
|
||||
</ul>
|
||||
</div><!-- /.navbar-collapse -->
|
||||
</div><!-- /.container-fluid -->
|
||||
</nav>
|
8
views/ng/navigation-detail.htm
Normal file
8
views/ng/navigation-detail.htm
Normal file
@ -0,0 +1,8 @@
|
||||
<ul class="switch-pane-tabs pull-right" {{ if eq .IsAdmin 1 }} style="width: 365px" {{ end }} role="tablist">
|
||||
<li><a tag="repositories" href="#/repositories?project_id=//vm.projectId//">// 'repositories' | tr //</a><span class="gutter">|</span></li>
|
||||
{{ if eq .IsAdmin 1 }}
|
||||
<li><a tag="replication" href="#/replication?project_id=//vm.projectId//">Replication</a><span class="gutter">|</span></li>
|
||||
{{ end }}
|
||||
<li><a tag="users" href="#/users?project_id=//vm.projectId//">// 'users' | tr //</a><span class="gutter">|</span></li>
|
||||
<li><a tag="logs" href="#/logs?project_id=//vm.projectId//">// 'logs' | tr //</a></li>
|
||||
</ul>
|
Loading…
Reference in New Issue
Block a user