diff --git a/controllers/accountsetting.go b/controllers/accountsetting.go index 03fe368cf..5d49e60d7 100644 --- a/controllers/accountsetting.go +++ b/controllers/accountsetting.go @@ -7,5 +7,5 @@ type AccountSettingController struct { // Get renders the account settings page func (asc *AccountSettingController) Get() { - asc.Forward("Account Settings", "account-settings.htm") + asc.Forward("page_title_account_setting", "account-settings.htm") } diff --git a/controllers/addnew.go b/controllers/addnew.go index 2bf6f1d57..c3ec9c571 100644 --- a/controllers/addnew.go +++ b/controllers/addnew.go @@ -24,7 +24,7 @@ func (anc *AddNewController) Get() { } if isAdmin && anc.AuthMode == "db_auth" { anc.Data["AddNew"] = true - anc.Forward("Add User", "sign-up.htm") + anc.Forward("page_title_add_new", "sign-up.htm") return } } diff --git a/controllers/adminoption.go b/controllers/adminoption.go index c0ae69bbb..d0a10c1fa 100644 --- a/controllers/adminoption.go +++ b/controllers/adminoption.go @@ -7,5 +7,5 @@ type AdminOptionController struct { // Get renders the admin options page func (aoc *AdminOptionController) Get() { - aoc.Forward("Admin Options", "admin-options.htm") + aoc.Forward("page_title_admin_option", "admin-options.htm") } diff --git a/controllers/base.go b/controllers/base.go index 07c3c106c..a806f55b3 100644 --- a/controllers/base.go +++ b/controllers/base.go @@ -50,11 +50,24 @@ func (b *BaseController) Prepare() { } } - sessionLang := b.GetSession("lang") - if sessionLang != nil { - b.SetSession("Lang", lang) - lang = sessionLang.(string) + langCookie, err := b.Ctx.Request.Cookie("language") + if err != nil { + log.Errorf("Error occurred in Request.Cookie: %v", err) } + if langCookie != nil { + lang = langCookie.Value + } + if len(lang) == 0 { + sessionLang := b.GetSession("lang") + if sessionLang != nil { + b.SetSession("Lang", lang) + lang = sessionLang.(string) + } else { + lang = defaultLang + } + } + + b.SetSession("Lang", lang) if _, exist := supportLanguages[lang]; !exist { //Check if support the request language. lang = defaultLang //Set default language if not supported. @@ -64,8 +77,20 @@ func (b *BaseController) Prepare() { Lang: lang, } + restLangs := make([]*langType, 0, len(langTypes)-1) + for _, v := range langTypes { + if lang != v.Lang { + restLangs = append(restLangs, v) + } else { + curLang.Name = v.Name + } + } + // Set language properties. + b.Lang = lang b.Data["Lang"] = curLang.Lang + b.Data["CurLang"] = curLang.Name + b.Data["RestLangs"] = restLangs authMode := strings.ToLower(os.Getenv("AUTH_MODE")) if authMode == "" { @@ -80,7 +105,7 @@ func (b *BaseController) Prepare() { func (b *BaseController) Forward(title, templateName string) { b.Layout = filepath.Join(prefixNg, "layout.htm") b.TplName = filepath.Join(prefixNg, templateName) - b.Data["Title"] = title + b.Data["Title"] = b.Tr(title) b.LayoutSections = make(map[string]string) b.LayoutSections["HeaderInclude"] = filepath.Join(prefixNg, viewPath, "header-include.htm") b.LayoutSections["FooterInclude"] = filepath.Join(prefixNg, viewPath, "footer-include.htm") @@ -131,12 +156,13 @@ func (cc *CommonController) LogOut() { // SwitchLanguage User can swith to prefered language func (cc *CommonController) SwitchLanguage() { lang := cc.GetString("lang") + hash := cc.GetString("hash") if _, exist := supportLanguages[lang]; !exist { lang = defaultLang } cc.SetSession("lang", lang) cc.Data["Lang"] = lang - cc.Redirect(cc.Ctx.Request.Header.Get("Referer"), http.StatusFound) + cc.Redirect(cc.Ctx.Request.Header.Get("Referer")+hash, http.StatusFound) } // UserExists checks if user exists when user input value in sign in form. @@ -170,19 +196,25 @@ func init() { beego.LoadAppConfig("ini", configPath) } + beego.AddFuncMap("i18n", i18n.Tr) + langs := strings.Split(beego.AppConfig.String("lang::types"), "|") names := strings.Split(beego.AppConfig.String("lang::names"), "|") supportLanguages = make(map[string]langType) langTypes = make([]*langType, 0, len(langs)) - for i, v := range langs { + + for i, lang := range langs { t := langType{ - Lang: v, + Lang: lang, Name: names[i], } langTypes = append(langTypes, &t) - supportLanguages[v] = t + supportLanguages[lang] = t + if err := i18n.SetMessage(lang, "static/i18n/"+"locale_"+lang+".ini"); err != nil { + log.Errorf("Fail to set message file: %s", err.Error()) + } } } diff --git a/controllers/dashboard.go b/controllers/dashboard.go index 78cff7472..bca215461 100644 --- a/controllers/dashboard.go +++ b/controllers/dashboard.go @@ -7,5 +7,5 @@ type DashboardController struct { // Get renders the dashboard page func (dc *DashboardController) Get() { - dc.Forward("Dashboard", "dashboard.htm") + dc.Forward("page_title_dashboard", "dashboard.htm") } diff --git a/controllers/index.go b/controllers/index.go index aee12f854..12339a64c 100644 --- a/controllers/index.go +++ b/controllers/index.go @@ -7,5 +7,5 @@ type IndexController struct { // Get renders the index page func (ic *IndexController) Get() { - ic.Forward("Index", "index.htm") + ic.Forward("page_title_index", "index.htm") } diff --git a/controllers/password.go b/controllers/password.go index b1dc3becc..1054473e0 100644 --- a/controllers/password.go +++ b/controllers/password.go @@ -59,7 +59,7 @@ func (cc *CommonController) SendEmail() { cc.CustomAbort(http.StatusInternalServerError, "Internal error.") } err = messageTemplate.Execute(message, messageDetail{ - Hint: cc.Tr("Warning: You're receiving this because you're requesting for changing password in Harbor, if it is not your operation, please ignore; otherwise, please click the link below"), + Hint: cc.Tr("reset_email_hint"), URL: harborURL, UUID: uuid, }) @@ -102,7 +102,7 @@ type ForgotPasswordController struct { // Get renders forgot password page func (fpc *ForgotPasswordController) Get() { - fpc.Forward("Forgot Password", "forgot-password.htm") + fpc.Forward("page_title_forgot_password", "forgot-password.htm") } // ResetPasswordController handles request to /resetPassword @@ -129,7 +129,7 @@ func (rpc *ResetPasswordController) Get() { if user != nil { rpc.Data["ResetUuid"] = user.ResetUUID - rpc.Forward("Reset Password", "reset-password.htm") + rpc.Forward("page_title_reset_password", "reset-password.htm") } else { rpc.Redirect("/", http.StatusFound) } diff --git a/controllers/project.go b/controllers/project.go index 68104ff0d..86bf299df 100644 --- a/controllers/project.go +++ b/controllers/project.go @@ -7,5 +7,5 @@ type ProjectController struct { // Get renders project page func (pc *ProjectController) Get() { - pc.Forward("My Projects", "project.htm") + pc.Forward("page_title_project", "project.htm") } diff --git a/controllers/repository.go b/controllers/repository.go index dbb08bbf2..58ad4dc7e 100644 --- a/controllers/repository.go +++ b/controllers/repository.go @@ -10,5 +10,5 @@ type RepositoryController struct { // Get renders repository page func (rc *RepositoryController) Get() { rc.Data["HarborRegUrl"] = os.Getenv("HARBOR_REG_URL") - rc.Forward("Repository", "repository.htm") + rc.Forward("page_title_repository", "repository.htm") } diff --git a/controllers/search.go b/controllers/search.go index 41d6a2927..e9c573751 100644 --- a/controllers/search.go +++ b/controllers/search.go @@ -7,5 +7,5 @@ type SearchController struct { // Get rendlers search bar func (sc *SearchController) Get() { - sc.Forward("Search", "search.htm") + sc.Forward("page_title_search", "search.htm") } diff --git a/controllers/signup.go b/controllers/signup.go index 4f2cd2b4f..9d46a368b 100644 --- a/controllers/signup.go +++ b/controllers/signup.go @@ -15,5 +15,5 @@ func (suc *SignUpController) Get() { suc.CustomAbort(http.StatusUnauthorized, "Status unauthorized.") } suc.Data["AddNew"] = false - suc.Forward("Sign Up", "sign-up.htm") + suc.Forward("page_title_sign_up", "sign-up.htm") } diff --git a/static/resources/css/destination.css b/static/resources/css/destination.css index 3a8b0842e..464a1ead4 100644 --- a/static/resources/css/destination.css +++ b/static/resources/css/destination.css @@ -1,3 +1,3 @@ .create-destination { - height: 235px; + height: 275px; } \ No newline at end of file diff --git a/static/resources/css/header.css b/static/resources/css/header.css index 24b1a7c81..50c94da22 100644 --- a/static/resources/css/header.css +++ b/static/resources/css/header.css @@ -30,7 +30,7 @@ nav .container-custom { } .search-icon { - background: url("/static/ng/resources/img/magnitude-glass.jpg") no-repeat 97% 6px; + background: url("/static/resources/img/magnitude-glass.jpg") no-repeat 97% 6px; background-size: 1.5em; background-color: #FFFFFF; } diff --git a/static/resources/css/project.css b/static/resources/css/project.css index c6b797e88..4fcf5609e 100644 --- a/static/resources/css/project.css +++ b/static/resources/css/project.css @@ -33,7 +33,7 @@ } .table-head-container { - width: 98%; + width: 96%; } .table-body-container { diff --git a/static/resources/js/components/details/retrieve-projects.directive.js b/static/resources/js/components/details/retrieve-projects.directive.js index a9da0a5b5..d69da1a7e 100644 --- a/static/resources/js/components/details/retrieve-projects.directive.js +++ b/static/resources/js/components/details/retrieve-projects.directive.js @@ -6,9 +6,9 @@ .module('harbor.details') .directive('retrieveProjects', retrieveProjects); - RetrieveProjectsController.$inject = ['$scope', 'nameFilter', '$filter', 'ListProjectService', '$location', 'getParameterByName', 'CurrentProjectMemberService']; + RetrieveProjectsController.$inject = ['$scope', 'nameFilter', '$filter', 'ListProjectService', '$location', 'getParameterByName', 'CurrentProjectMemberService', '$window']; - function RetrieveProjectsController($scope, nameFilter, $filter, ListProjectService, $location, getParameterByName, CurrentProjectMemberService) { + function RetrieveProjectsController($scope, nameFilter, $filter, ListProjectService, $location, getParameterByName, CurrentProjectMemberService, $window) { var vm = this; vm.projectName = ''; @@ -100,7 +100,7 @@ } function getCurrentProjectMemberFailed(data, status) { - console.log('Use has no member for current project:' + status); + console.log('Use has no member for current project:' + status + ', location.url:' + $location.url()); vm.isProjectMember = false; } diff --git a/static/resources/js/components/log/list-log.directive.html b/static/resources/js/components/log/list-log.directive.html index 54a2f62a8..dd101668b 100644 --- a/static/resources/js/components/log/list-log.directive.html +++ b/static/resources/js/components/log/list-log.directive.html @@ -15,15 +15,15 @@
- - - - - - - - -
// 'username' | tr //// 'repository_name' | tr //// 'operation' | tr //// 'timestamp' | tr //
//log.username////log.repo_name////log.operation////log.op_time | dateL : 'YYYY-MM-DD HH:mm:ss'//
+ + // 'username' | tr //// 'repository_name' | tr //// 'operation' | tr //// 'timestamp' | tr // + + + + //log.username////log.repo_name////log.operation////log.op_time | dateL : 'YYYY-MM-DD HH:mm:ss'// + + +
diff --git a/static/resources/js/components/optional-menu/optional-menu.directive.js b/static/resources/js/components/optional-menu/optional-menu.directive.js index 1fd270e04..e0f5e32ec 100644 --- a/static/resources/js/components/optional-menu/optional-menu.directive.js +++ b/static/resources/js/components/optional-menu/optional-menu.directive.js @@ -25,7 +25,8 @@ function setLanguage(language) { I18nService().setCurrentLanguage(language); - $window.location.href = '/language?lang=' + language; + var hash = $window.location.hash; + $window.location.href = '/language?lang=' + language + '&hash=' + encodeURIComponent(hash); } function logOut() { LogOutService() diff --git a/static/resources/js/components/project-member/add-project-member.directive.js b/static/resources/js/components/project-member/add-project-member.directive.js index 8783b1cda..2a79db0a3 100644 --- a/static/resources/js/components/project-member/add-project-member.directive.js +++ b/static/resources/js/components/project-member/add-project-member.directive.js @@ -52,6 +52,10 @@ } function addProjectMemberFailed(data, status, headers) { + if(status === 403) { + vm.hasError = true; + vm.errorMessage = 'failed_to_add_member'; + } if(status === 409 && pm.username != '') { vm.hasError = true; vm.errorMessage = 'username_already_exist'; diff --git a/static/resources/js/components/project-member/edit-project-member.directive.html b/static/resources/js/components/project-member/edit-project-member.directive.html index 830278346..e66e14956 100644 --- a/static/resources/js/components/project-member/edit-project-member.directive.html +++ b/static/resources/js/components/project-member/edit-project-member.directive.html @@ -2,10 +2,10 @@ - + - + - + \ No newline at end of file diff --git a/static/resources/js/components/project-member/list-project-member.directive.js b/static/resources/js/components/project-member/list-project-member.directive.js index 61517bfd7..315aa7a4f 100644 --- a/static/resources/js/components/project-member/list-project-member.directive.js +++ b/static/resources/js/components/project-member/list-project-member.directive.js @@ -6,9 +6,9 @@ .module('harbor.project.member') .directive('listProjectMember', listProjectMember); - ListProjectMemberController.$inject = ['$scope', 'ListProjectMemberService', 'DeleteProjectMemberService', 'getParameterByName', '$location', 'currentUser', '$filter', 'trFilter']; + ListProjectMemberController.$inject = ['$scope', 'ListProjectMemberService', 'DeleteProjectMemberService', 'getParameterByName', '$location', 'currentUser', '$filter', 'trFilter', '$window']; - function ListProjectMemberController($scope, ListProjectMemberService, DeleteProjectMemberService, getParameterByName, $location, currentUser, $filter, trFilter) { + function ListProjectMemberController($scope, ListProjectMemberService, DeleteProjectMemberService, getParameterByName, $location, currentUser, $filter, trFilter, $window) { $scope.subsTabPane = 30; @@ -71,11 +71,13 @@ function getProjectMemberComplete(response) { vm.user = currentUser.get(); - vm.projectMembers = response.data; + vm.projectMembers = response.data || []; } function getProjectMemberFailed(response) { console.log('Failed get project members:' + response); + vm.projectMembers = []; + $location.url('repositories').search('project_id', vm.projectId); } } diff --git a/static/resources/js/components/replication/create-policy.directive.html b/static/resources/js/components/replication/create-policy.directive.html index 22f00b63e..5decf7ccb 100644 --- a/static/resources/js/components/replication/create-policy.directive.html +++ b/static/resources/js/components/replication/create-policy.directive.html @@ -1,5 +1,5 @@ -