Merge branch 'new-version-of-ui' of https://github.com/vmware/harbor into new-version-of-ui

This commit is contained in:
kunw 2016-05-24 10:54:23 +08:00
commit ce2454472b
38 changed files with 161 additions and 51 deletions

View File

@ -1,9 +1,11 @@
package ng package ng
// AccountSettingController handles request to /ng/account_setting
type AccountSettingController struct { type AccountSettingController struct {
BaseController BaseController
} }
// Get renders the account settings page
func (asc *AccountSettingController) Get() { func (asc *AccountSettingController) Get() {
asc.Forward("Account Settings", "account-settings.htm") asc.Forward("Account Settings", "account-settings.htm")
} }

View File

@ -1,9 +1,11 @@
package ng package ng
// AdminOptionController handles requests to /ng/admin_option
type AdminOptionController struct { type AdminOptionController struct {
BaseController BaseController
} }
// Get renders the admin options page
func (aoc *AdminOptionController) Get() { func (aoc *AdminOptionController) Get() {
aoc.Forward("Admin Options", "admin-options.htm") aoc.Forward("Admin Options", "admin-options.htm")
} }

View File

@ -11,6 +11,7 @@ import (
"github.com/vmware/harbor/utils/log" "github.com/vmware/harbor/utils/log"
) )
// BaseController wraps common methods such as i18n support, forward, which can be leveraged by other UI render controllers.
type BaseController struct { type BaseController struct {
beego.Controller beego.Controller
i18n.Locale i18n.Locale
@ -84,32 +85,37 @@ func (b *BaseController) Prepare() {
} }
func (bc *BaseController) Forward(title, templateName string) { // Forward to setup layout and template for content for a page.
bc.Layout = filepath.Join(prefixNg, "layout.htm") func (b *BaseController) Forward(title, templateName string) {
bc.TplName = filepath.Join(prefixNg, templateName) b.Layout = filepath.Join(prefixNg, "layout.htm")
bc.Data["Title"] = title b.TplName = filepath.Join(prefixNg, templateName)
bc.LayoutSections = make(map[string]string) b.Data["Title"] = title
bc.LayoutSections["HeaderInclude"] = filepath.Join(prefixNg, viewPath, "header-include.htm") b.LayoutSections = make(map[string]string)
bc.LayoutSections["FooterInclude"] = filepath.Join(prefixNg, viewPath, "footer-include.htm") b.LayoutSections["HeaderInclude"] = filepath.Join(prefixNg, viewPath, "header-include.htm")
bc.LayoutSections["HeaderContent"] = filepath.Join(prefixNg, viewPath, "header-content.htm") b.LayoutSections["FooterInclude"] = filepath.Join(prefixNg, viewPath, "footer-include.htm")
bc.LayoutSections["FooterContent"] = filepath.Join(prefixNg, viewPath, "footer-content.htm") b.LayoutSections["HeaderContent"] = filepath.Join(prefixNg, viewPath, "header-content.htm")
b.LayoutSections["FooterContent"] = filepath.Join(prefixNg, viewPath, "footer-content.htm")
} }
var langTypes []*langType var langTypes []*langType
// CommonController handles request from UI that doesn't expect a page, such as /SwitchLanguage /logout ...
type CommonController struct { type CommonController struct {
BaseController BaseController
} }
// Render returns nil.
func (cc *CommonController) Render() error { func (cc *CommonController) Render() error {
return nil return nil
} }
// LogOut Habor UI
func (cc *CommonController) LogOut() { func (cc *CommonController) LogOut() {
cc.DestroySession() cc.DestroySession()
} }
// SwitchLanguage User can swith to prefered language
func (cc *CommonController) SwitchLanguage() { func (cc *CommonController) SwitchLanguage() {
lang := cc.GetString("lang") lang := cc.GetString("lang")
if _, exist := supportLanguages[lang]; exist { if _, exist := supportLanguages[lang]; exist {

View File

@ -1,9 +1,11 @@
package ng package ng
// DashboardController handles requests to /ng/dashboard
type DashboardController struct { type DashboardController struct {
BaseController BaseController
} }
// Get renders the dashboard page
func (dc *DashboardController) Get() { func (dc *DashboardController) Get() {
dc.Forward("Dashboard", "dashboard.htm") dc.Forward("Dashboard", "dashboard.htm")
} }

View File

@ -1,9 +1,11 @@
package ng package ng
// IndexController handles request to /ng
type IndexController struct { type IndexController struct {
BaseController BaseController
} }
// Get renders the index page
func (ic *IndexController) Get() { func (ic *IndexController) Get() {
ic.Forward("Index", "index.htm") ic.Forward("Index", "index.htm")
} }

View File

@ -8,10 +8,12 @@ import (
"github.com/vmware/harbor/utils/log" "github.com/vmware/harbor/utils/log"
) )
// NavigationHeaderController handles requests to /ng/navigation_header
type NavigationHeaderController struct { type NavigationHeaderController struct {
BaseController BaseController
} }
// Get renders user's navigation header
func (nhc *NavigationHeaderController) Get() { func (nhc *NavigationHeaderController) Get() {
sessionUserID := nhc.GetSession("userId") sessionUserID := nhc.GetSession("userId")
var hasLoggedIn bool var hasLoggedIn bool

View File

@ -8,10 +8,12 @@ import (
"github.com/vmware/harbor/utils/log" "github.com/vmware/harbor/utils/log"
) )
// OptionalMenuController handles request to /ng/optional_menu
type OptionalMenuController struct { type OptionalMenuController struct {
BaseController BaseController
} }
// Get renders optional menu, Admin user has "Add User" menu
func (omc *OptionalMenuController) Get() { func (omc *OptionalMenuController) Get() {
sessionUserID := omc.GetSession("userId") sessionUserID := omc.GetSession("userId")

View File

@ -95,10 +95,12 @@ func (cc *CommonController) SendEmail() {
} }
// ForgotPasswordController handles requests to /ng/forgot_password
type ForgotPasswordController struct { type ForgotPasswordController struct {
BaseController BaseController
} }
// Get renders forgot password page
func (fpc *ForgotPasswordController) Get() { func (fpc *ForgotPasswordController) Get() {
fpc.Forward("Forgot Password", "forgot-password.htm") fpc.Forward("Forgot Password", "forgot-password.htm")
} }

View File

@ -1,9 +1,11 @@
package ng package ng
// ProjectController handles requests to /ng/projec
type ProjectController struct { type ProjectController struct {
BaseController BaseController
} }
// Get renders project page
func (pc *ProjectController) Get() { func (pc *ProjectController) Get() {
pc.Forward("My Projects", "project.htm") pc.Forward("My Projects", "project.htm")
} }

View File

@ -2,10 +2,12 @@ package ng
import "os" import "os"
// RepositoryController handles request to /ng/repository
type RepositoryController struct { type RepositoryController struct {
BaseController BaseController
} }
// Get renders repository page
func (rc *RepositoryController) Get() { func (rc *RepositoryController) Get() {
rc.Data["HarborRegUrl"] = os.Getenv("HARBOR_REG_URL") rc.Data["HarborRegUrl"] = os.Getenv("HARBOR_REG_URL")
rc.Forward("Repository", "repository.htm") rc.Forward("Repository", "repository.htm")

View File

@ -1,9 +1,11 @@
package ng package ng
// SearchController handles request to ng/search
type SearchController struct { type SearchController struct {
BaseController BaseController
} }
// Get rendlers search bar
func (sc *SearchController) Get() { func (sc *SearchController) Get() {
sc.Forward("Search", "search.htm") sc.Forward("Search", "search.htm")
} }

View File

@ -1,9 +1,11 @@
package ng package ng
// SignUpController handles requests to /ng/sign_up
type SignUpController struct { type SignUpController struct {
BaseController BaseController
} }
// Get renders sign up page
func (suc *SignUpController) Get() { func (suc *SignUpController) Get() {
suc.Forward("Sign Up", "sign-up.htm") suc.Forward("Sign Up", "sign-up.htm")
} }

59
static/ng/Gruntfile.js Normal file
View File

@ -0,0 +1,59 @@
/*global module:false*/
module.exports = function(grunt) {
'use strict';
// Project configuration.
grunt.initConfig({
// Task configuration.
jshint: {
options: {
browser: true,
curly: true,
freeze: true,
bitwise: true,
eqeqeq: true,
strict: true,
immed: true,
latedef: false,
newcap: false,
smarttabs: true,
noarg: true,
devel: true,
sub: true,
undef: true,
unused: false,
boss: true,
eqnull: true,
globals: {
jQuery: true,
angular: true,
$: true,
}
},
gruntfile: {
src: 'Gruntfile.js'
},
scripts: {
src: ['resources/**/**/*.js']
}
},
watch: {
gruntfile: {
files: '<%= jshint.gruntfile.src %>',
tasks: ['jshint:gruntfile']
},
scripts: {
files: '<%= jshint.scripts.src %>',
tasks: ['jshint:scripts']
}
}
});
// These plugins provide necessary tasks.
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-watch');
// Default task.
grunt.registerTask('default', ['jshint']);
};

10
static/ng/package.json Normal file
View File

@ -0,0 +1,10 @@
{
"engines": {
"node": ">= 0.10.0"
},
"devDependencies": {
"grunt": "~0.4.5",
"grunt-contrib-jshint": "~0.10.0",
"grunt-contrib-watch": "~0.6.1"
}
}

View File

@ -58,7 +58,7 @@
if($routeParams.project_id){ if($routeParams.project_id){
angular.forEach(vm.projects, function(value, index) { angular.forEach(vm.projects, function(value, index) {
if(value['ProjectId'] == $routeParams.project_id) { if(value['ProjectId'] === $routeParams.project_id) {
vm.selectedProject = value; vm.selectedProject = value;
} }
}); });
@ -117,7 +117,7 @@
controller: RetrieveProjectsController, controller: RetrieveProjectsController,
bindToController: true, bindToController: true,
controllerAs: 'vm' controllerAs: 'vm'
} };
return directive; return directive;

View File

@ -42,7 +42,7 @@
controller: SwitchPaneProjectsController, controller: SwitchPaneProjectsController,
controllerAs: 'vm', controllerAs: 'vm',
bindToController: true bindToController: true
} };
return directive; return directive;

View File

@ -24,7 +24,7 @@
vm.op = []; vm.op = [];
vm.op.push('all'); vm.op.push('all');
function checkOperation(e) { function checkOperation(e) {
if(e.checked == 'all') { if(e.checked === 'all') {
vm.opCreate = vm.opAll; vm.opCreate = vm.opAll;
vm.opPull = vm.opAll; vm.opPull = vm.opAll;
vm.opPush = vm.opAll; vm.opPush = vm.opAll;
@ -48,7 +48,7 @@
if(vm.opDelete) { if(vm.opDelete) {
vm.op.push('delete'); vm.op.push('delete');
} }
if(vm.opOthers && vm.others != "") { if(vm.opOthers && vm.others !== "") {
vm.op.push(vm.others); vm.op.push(vm.others);
} }
} }

View File

@ -33,7 +33,7 @@
retrieve(vm.queryParams); retrieve(vm.queryParams);
function search(e) { function search(e) {
if(e.op[0] == 'all') { if(e.op[0] === 'all') {
vm.queryParams.keywords = ''; vm.queryParams.keywords = '';
}else { }else {
vm.queryParams.keywords = e.op.join('/') ; vm.queryParams.keywords = e.op.join('/') ;
@ -68,7 +68,7 @@
} }
function toUTCSeconds(date, hour, min, sec) { function toUTCSeconds(date, hour, min, sec) {
if(date == "") { if(date === "") {
return 0; return 0;
} }
@ -96,7 +96,7 @@
controller: ListLogController, controller: ListLogController,
controllerAs: 'vm', controllerAs: 'vm',
bindToController: true bindToController: true
} };
return directive; return directive;
} }

View File

@ -55,7 +55,7 @@
vm.hasError = true; vm.hasError = true;
vm.errorMessage = 'username_already_exist'; vm.errorMessage = 'username_already_exist';
} }
if(status == 404) { if(status === 404) {
vm.hasError = true; vm.hasError = true;
vm.errorMessage = 'username_does_not_exist'; vm.errorMessage = 'username_does_not_exist';
} }
@ -76,7 +76,8 @@
'controller': AddProjectMemberController, 'controller': AddProjectMemberController,
'controllerAs': 'vm', 'controllerAs': 'vm',
'bindToController': true 'bindToController': true
} };
return directive; return directive;
} }

View File

@ -60,7 +60,8 @@
controller: ListProjectMemberController, controller: ListProjectMemberController,
controllerAs: 'vm', controllerAs: 'vm',
bindToController: true bindToController: true
} };
return directive; return directive;
} }

View File

@ -24,8 +24,8 @@
for(var i = 0; i < r.length; i++) { for(var i = 0; i < r.length; i++) {
var role = r[i]; var role = r[i];
if(query.key == 'roleName' && role.roleName == query.value if(query.key === 'roleName' && role.roleName === query.value
|| query.key == 'roleId' && role.id == query.value) { || query.key === 'roleId' && role.id === query.value) {
return role; return role;
} }
} }

View File

@ -44,7 +44,7 @@
vm.hasError = true; vm.hasError = true;
vm.errorMessage = 'project_already_exist'; vm.errorMessage = 'project_already_exist';
} }
if(status == 500) { if(status === 500) {
vm.hasError = true; vm.hasError = true;
vm.errorMessage = 'project_name_is_invalid'; vm.errorMessage = 'project_name_is_invalid';
} }

View File

@ -12,7 +12,7 @@
var vm = this; var vm = this;
vm.toggle = toggle; vm.toggle = toggle;
if(vm.isPublic == 1) { if(vm.isPublic === 1) {
vm.isPublic = true; vm.isPublic = true;
}else{ }else{
vm.isPublic = false; vm.isPublic = false;

View File

@ -98,7 +98,7 @@
controller: ListRepositoryController, controller: ListRepositoryController,
controllerAs: 'vm', controllerAs: 'vm',
bindToController: true bindToController: true
} };
return directive; return directive;

View File

@ -40,7 +40,7 @@
$scope.$emit('modalTitle', $filter('tr')('alert_delete_tag_title', [e.tag])); $scope.$emit('modalTitle', $filter('tr')('alert_delete_tag_title', [e.tag]));
var message; var message;
if(vm.tags.length == 1) { if(vm.tags.length === 1) {
message = $filter('tr')('alert_delete_last_tag', [e.tag]); message = $filter('tr')('alert_delete_last_tag', [e.tag]);
}else { }else {
message = $filter('tr')('alert_delete_tag', [e.tag]); message = $filter('tr')('alert_delete_tag', [e.tag]);

View File

@ -81,15 +81,15 @@
'<div class="form-group"><label class="col-sm-3 control-label">Created</label>' + '<div class="form-group"><label class="col-sm-3 control-label">Created</label>' +
'<div class="col-sm-9"><p class="form-control-static">' + ctrl.manifest['Created'] + '</p></div></div>' + '<div class="col-sm-9"><p class="form-control-static">' + ctrl.manifest['Created'] + '</p></div></div>' +
'<div class="form-group"><label class="col-sm-3 control-label">Duration Days</label>' + '<div class="form-group"><label class="col-sm-3 control-label">Duration Days</label>' +
'<div class="col-sm-9"><p class="form-control-static">' + (ctrl.manifest['Duration Days'] == '' ? 'N/A' : ctrl.manifest['Duration Days']) + ' days</p></div></div>' + '<div class="col-sm-9"><p class="form-control-static">' + (ctrl.manifest['Duration Days'] === '' ? 'N/A' : ctrl.manifest['Duration Days']) + ' days</p></div></div>' +
'<div class="form-group"><label class="col-sm-3 control-label">Author</label>' + '<div class="form-group"><label class="col-sm-3 control-label">Author</label>' +
'<div class="col-sm-9"><p class="form-control-static">' + (ctrl.manifest['Author'] == '' ? 'N/A' : ctrl.manifest['Author']) + '</p></div></div>' + '<div class="col-sm-9"><p class="form-control-static">' + (ctrl.manifest['Author'] === '' ? 'N/A' : ctrl.manifest['Author']) + '</p></div></div>' +
'<div class="form-group"><label class="col-sm-3 control-label">Architecture</label>' + '<div class="form-group"><label class="col-sm-3 control-label">Architecture</label>' +
'<div class="col-sm-9"><p class="form-control-static">' + (ctrl.manifest['Architecture'] == '' ? 'N/A' : ctrl.manifest['Architecture']) + '</p></div></div>' + '<div class="col-sm-9"><p class="form-control-static">' + (ctrl.manifest['Architecture'] === '' ? 'N/A' : ctrl.manifest['Architecture']) + '</p></div></div>' +
'<div class="form-group"><label class="col-sm-3 control-label">Docker Version</label>' + '<div class="form-group"><label class="col-sm-3 control-label">Docker Version</label>' +
'<div class="col-sm-9"><p class="form-control-static">' + (ctrl.manifest['Docker Version'] == '' ? 'N/A' : ctrl.manifest['Docker Version']) + '</p></div></div>' + '<div class="col-sm-9"><p class="form-control-static">' + (ctrl.manifest['Docker Version'] === '' ? 'N/A' : ctrl.manifest['Docker Version']) + '</p></div></div>' +
'<div class="form-group"><label class="col-sm-3 control-label">OS</label>' + '<div class="form-group"><label class="col-sm-3 control-label">OS</label>' +
'<div class="col-sm-9"><p class="form-control-static">' + (ctrl.manifest['OS'] == '' ? 'N/A' : ctrl.manifest['OS']) + '</p></div></div>' + '<div class="col-sm-9"><p class="form-control-static">' + (ctrl.manifest['OS'] === '' ? 'N/A' : ctrl.manifest['OS']) + '</p></div></div>' +
'</form>'; '</form>';
return content; return content;
} }

View File

@ -60,7 +60,8 @@
'controller': SignInController, 'controller': SignInController,
'controllerAs': 'vm', 'controllerAs': 'vm',
'bindToController': true 'bindToController': true
} };
return directive; return directive;
} }

View File

@ -11,7 +11,7 @@
function ToggleAdminController($scope, ToggleAdminService) { function ToggleAdminController($scope, ToggleAdminService) {
var vm = this; var vm = this;
vm.isAdmin = (vm.hasAdminRole == 1) ? true : false; vm.isAdmin = (vm.hasAdminRole === 1) ? true : false;
vm.toggle = toggle; vm.toggle = toggle;
function toggle() { function toggle() {

View File

@ -21,7 +21,7 @@
ctrl.$validators.compareTo = validator; ctrl.$validators.compareTo = validator;
function validator(modelValue) { function validator(modelValue) {
return modelValue == scope.otherModelValue; return modelValue === scope.otherModelValue;
} }
scope.$watch("otherModelValue", function(current, origin) { scope.$watch("otherModelValue", function(current, origin) {

View File

@ -19,8 +19,14 @@
name = name.replace(/[\[\]]/g, "\\$&"); name = name.replace(/[\[\]]/g, "\\$&");
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"), var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
results = regex.exec(url); results = regex.exec(url);
if (!results) return null; if (!results) {
if (!results[2]) return ''; return null;
}
if (!results[2]) {
return '';
}
return decodeURIComponent(results[2].replace(/\+/g, " ")); return decodeURIComponent(results[2].replace(/\+/g, " "));
} }
} }

View File

@ -20,7 +20,7 @@
unset: function() { unset: function() {
$cookies.remove('user', {'path': '/'}); $cookies.remove('user', {'path': '/'});
} }
} };
} }
currentProjectMember.$inject = ['$cookies']; currentProjectMember.$inject = ['$cookies'];
@ -36,7 +36,7 @@
unset: function() { unset: function() {
$cookies.remove('member', {'path': '/'}); $cookies.remove('member', {'path': '/'});
} }
} };
} }
})(); })();

View File

@ -35,10 +35,10 @@
input = input || []; input = input || [];
var filteredResults = []; var filteredResults = [];
if (filterInput != '') { if (filterInput !== '') {
for(var i = 0; i < input.length; i++) { for(var i = 0; i < input.length; i++) {
var item = input[i]; var item = input[i];
if((key == "" && item.indexOf(filterInput) >= 0) || (key != "" && item[key].indexOf(filterInput) >= 0)) { if((key === "" && item.indexOf(filterInput) >= 0) || (key !== "" && item[key].indexOf(filterInput) >= 0)) {
filteredResults.push(item); filteredResults.push(item);
continue; continue;
} }

View File

@ -32,7 +32,7 @@
controller: NavigationDetailsController, controller: NavigationDetailsController,
controllerAs: 'vm', controllerAs: 'vm',
bindToController: true bindToController: true
} };
return directive; return directive;

View File

@ -22,13 +22,13 @@
controller: NavigationHeaderController, controller: NavigationHeaderController,
controllerAs: 'vm', controllerAs: 'vm',
bindToController: true bindToController: true
} };
return directive; return directive;
function link(scope, element, attrs, ctrl) { function link(scope, element, attrs, ctrl) {
var visited = ctrl.url; var visited = ctrl.url;
if (visited != "/ng") { if (visited !== "/ng") {
element.find('a[href*="' + visited + '"]').addClass('active'); element.find('a[href*="' + visited + '"]').addClass('active');
} }
element.find('a').on('click', click); element.find('a').on('click', click);

View File

@ -59,7 +59,7 @@
} }
function showAddButton() { function showAddButton() {
if(vm.publicity == 0) { if(vm.publicity === 0) {
return true; return true;
}else{ }else{
return false; return false;

View File

@ -18,15 +18,16 @@
}; };
var isSupportLanguage = function(language) { var isSupportLanguage = function(language) {
for (var i in supportLanguages) { for (var i in supportLanguages) {
if(language == i) { if(language === i) {
return true; return true;
} }
} }
return false; return false;
} };
return tr; return tr;
function tr() { function tr() {
return { return {
'setCurrentLanguage': function(language) { 'setCurrentLanguage': function(language) {
if(!angular.isDefined(language) || !isSupportLanguage(language)) { if(!angular.isDefined(language) || !isSupportLanguage(language)) {
@ -52,7 +53,8 @@
'getValue': function(key) { 'getValue': function(key) {
return messages[key]; return messages[key];
} }
} };
} }
} }

View File

@ -17,8 +17,9 @@
headers: {'Content-Type': 'application/x-www-form-urlencoded'}, headers: {'Content-Type': 'application/x-www-form-urlencoded'},
transformRequest: function(obj) { transformRequest: function(obj) {
var str = []; var str = [];
for(var p in obj) for(var p in obj) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p])); str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
return str.join("&"); return str.join("&");
}, },
data: {'reset_uuid': uuid, 'password': password} data: {'reset_uuid': uuid, 'password': password}

View File

@ -19,8 +19,9 @@
headers: {'Content-Type': 'application/x-www-form-urlencoded'}, headers: {'Content-Type': 'application/x-www-form-urlencoded'},
transformRequest: function(obj) { transformRequest: function(obj) {
var str = []; var str = [];
for(var p in obj) for(var p in obj) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p])); str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
return str.join("&"); return str.join("&");
}, },
data: {'principal': principal, 'password': password} data: {'principal': principal, 'password': password}