updates for i18n and miscellaneous.

This commit is contained in:
kunw 2016-06-28 23:42:05 +08:00
parent e088637274
commit e77e7ba0b0
35 changed files with 194 additions and 96 deletions

View File

@ -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")
}

View File

@ -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
}
}

View File

@ -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")
}

View File

@ -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())
}
}
}

View File

@ -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")
}

View File

@ -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")
}

View File

@ -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)
}

View File

@ -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")
}

View File

@ -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")
}

View File

@ -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")
}

View File

@ -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")
}

View File

@ -1,3 +1,3 @@
.create-destination {
height: 235px;
height: 275px;
}

View File

@ -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;
}

View File

@ -33,7 +33,7 @@
}
.table-head-container {
width: 98%;
width: 96%;
}
.table-body-container {

View File

@ -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;
}

View File

@ -15,15 +15,15 @@
<div class="pane">
<div class="sub-pane">
<table class="table table-pane">
<thead>
<th>// 'username' | tr //</th><th>// 'repository_name' | tr //</th><th>// 'operation' | tr //</th><th>// 'timestamp' | tr //</th>
</thead>
<tbody>
<tr ng-repeat="log in vm.logs">
<td>//log.username//</td><td>//log.repo_name//</td><td>//log.operation//</td><td>//log.op_time | dateL : 'YYYY-MM-DD HH:mm:ss'//</td>
</tr>
</tbody>
</table>
<thead>
<th>// 'username' | tr //</th><th>// 'repository_name' | tr //</th><th>// 'operation' | tr //</th><th>// 'timestamp' | tr //</th>
</thead>
<tbody>
<tr ng-repeat="log in vm.logs">
<td>//log.username//</td><td>//log.repo_name//</td><td>//log.operation//</td><td>//log.op_time | dateL : 'YYYY-MM-DD HH:mm:ss'//</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>

View File

@ -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()

View File

@ -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';

View File

@ -2,10 +2,10 @@
<td><switch-role roles="vm.roles" edit-mode="vm.editMode" user-id="vm.userId" role-name="vm.roleName"></switch-role></td>
<td>
<a ng-show="vm.userId != vm.currentUserId" href="javascript:void(0);" ng-click="vm.updateProjectMember({projectId: vm.projectId, userId: vm.userId, roleId: vm.roleId})">
<span ng-if="!vm.editMode" class="glyphicon glyphicon-pencil" title="Edit"></span><span ng-if="vm.editMode" class="glyphicon glyphicon-ok" title="Confirm">
<span ng-if="!vm.editMode" class="glyphicon glyphicon-pencil" title="// 'edit' | tr //"></span><span ng-if="vm.editMode" class="glyphicon glyphicon-ok" title="Confirm">
</a>
<a ng-show="vm.userId != vm.currentUserId" href="javascript:void(0);" ng-click="vm.cancelUpdate()" title="Cancel">
<a ng-show="vm.userId != vm.currentUserId" href="javascript:void(0);" ng-click="vm.cancelUpdate()" title="// 'cancel' | tr //">
<span ng-if="vm.editMode" class="glyphicon glyphicon-repeat"></span>
</a>
<a ng-show="vm.userId != vm.currentUserId && !vm.editMode" href="javascript:void(0);" ng-click="vm.deleteProjectMember()" title="Delete"><span class="glyphicon glyphicon-trash"></span></a>
<a ng-show="vm.userId != vm.currentUserId && !vm.editMode" href="javascript:void(0);" ng-click="vm.deleteProjectMember()" title="// 'delete' | tr //"><span class="glyphicon glyphicon-trash"></span></a>
</td>

View File

@ -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);
}
}

View File

@ -1,5 +1,5 @@
<modal-dialog modal-title="//vm.modalTitle//" modal-message="//vm.modalMessage//" confirm-only="true"></modal-dialog>
<div class="modal fade" id="createPolicyModal" tabindex="-1" role="dialog">
<div class="modal fade" data-backdrop="static" id="createPolicyModal" tabindex="-1" role="dialog">
<div class="modal-dialog">
<form name="form" class="form-horizontal css-form" novalidate>
<div class="modal-content">
@ -59,7 +59,7 @@
<div class="form-group col-md-12 form-group-custom">
<label for="endpoint" class="col-md-3 control-label">// 'endpoint' | tr //:</label>
<div class="col-md-9">
<input type="text" class="form-control form-control-custom" id="endpoint" ng-model="replication.destination.endpoint" name="uEndpoint" ng-value="vm.endpoint" required ng-disabled="!vm.targetEditable">
<input type="text" class="form-control form-control-custom" id="endpoint" ng-model="replication.destination.endpoint" name="uEndpoint" ng-value="vm.endpoint" required ng-disabled="!vm.targetEditable || !vm.checkedAddTarget">
<div ng-messages="form.$submitted && form.uEndpoint.$error">
<span ng-message="required">// 'endpoint_is_required' | tr //</span>
</div>
@ -68,19 +68,25 @@
<div class="form-group col-md-12 form-group-custom">
<label for="username" class="col-md-3 control-label">// 'username' | tr //:</label>
<div class="col-md-9">
<input type="text" class="form-control" id="username" ng-model="replication.destination.username" name="uUsername" ng-value="vm.username" ng-disabled="!vm.targetEditable">
<input type="text" class="form-control" id="username" ng-model="replication.destination.username" name="uUsername" ng-value="vm.username" ng-disabled="!vm.targetEditable || !vm.checkedAddTarget">
</div>
</div>
<div class="form-group col-md-12 form-group-custom">
<label for="password" class="col-md-3 control-label">// 'password' | tr //:</label>
<div class="col-md-9">
<input type="password" class="form-control" id="password" ng-model="replication.destination.password" name="uPassword" ng-value="vm.password" ng-disabled="!vm.targetEditable">
<input type="password" class="form-control" id="password" ng-model="replication.destination.password" name="uPassword" ng-value="vm.password" ng-disabled="!vm.targetEditable || !vm.checkedAddTarget">
</div>
</div>
<div class="form-group col-md-12 form-group-custom">
<div class="col-md-3"></div>
<div class="col-md-9">
<button type="button" class="btn btn-default" ng-click="vm.pingDestination()" ng-disabled="vm.notAvailable">// 'test_connection' | tr //</button>
<button type="button" class="btn btn-default" ng-click="vm.pingDestination()" ng-disabled="vm.notAvailable || !vm.pingAvailable">// 'test_connection' | tr //</button>
</div>
</div>
<div class="form-group col-md-12 form-group-custom">
<div class="col-md-3"></div>
<div class="col-md-9">
<span>// vm.pingMessage //</span>
</div>
</div>
</div>

View File

@ -38,6 +38,8 @@
vm.targetEditable = true;
vm.checkedAddTarget = false;
vm.notAvailable = false;
vm.pingAvailable = true;
vm.pingMessage = '';
$scope.$watch('vm.destinations', function(current) {
if(current) {
@ -61,6 +63,7 @@
vm1.endpoint = '';
vm1.username = '';
vm1.password = '';
vm.pingMessage = '';
}
});
@ -95,7 +98,7 @@
}
function addNew() {
$filter('tr')('add_new_policy', []);
vm.modalTitle = $filter('tr')('add_new_policy', []);
vm.targetEditable = true;
vm0.name = '';
vm0.description = '';
@ -107,7 +110,7 @@
console.log('Edit policy ID:' + policyId);
vm.policyId = policyId;
vm.targetEditable = true;
$filter('tr')('edit_policy', []);
vm.modalTitle = $filter('tr')('edit_policy', []);
ListReplicationPolicyService(policyId)
.success(listReplicationPolicySuccess)
@ -131,12 +134,6 @@
CreateDestinationService(target.name, target.endpoint, target.username, target.password)
.success(createDestinationSuccess)
.error(createDestinationFailed);
}else{
target.name = vm1.selection.name;
console.log('Update target ID:' + vm.targetId);
UpdateDestinationService(vm.targetId, target)
.success(updateDestinationSuccess)
.error(updateDestinationFailed);
}
}
@ -170,10 +167,10 @@
if(vm.checkedAddTarget) {
target.name = vm1.name;
}else{
target.name = vm1.selection.name;
}
vm.pingAvailable = false;
PingDestinationService(target)
.success(pingDestinationSuccess)
.error(pingDestinationFailed);
@ -274,10 +271,12 @@
console.log('Failed update destination.');
}
function pingDestinationSuccess(data, status) {
alert($filter('tr')('successful_ping_target', []));
vm.pingAvailable = true;
vm.pingMessage = $filter('tr')('successful_ping_target', []);
}
function pingDestinationFailed(data, status) {
alert($filter('tr')('failed_ping_target', []) + data);
vm.pingAvailable = true;
vm.pingMessage = $filter('tr')('failed_ping_target', []) + (data && data.length > 0 ? ':' + data : '.');
}
}
@ -320,6 +319,8 @@
ctrl.checkedAddTarget = false;
ctrl.targetEditable = true;
ctrl.notAvailable = false;
ctrl.pingMessage = '';
ctrl.pingAvailable = true;
ctrl.prepareDestination();
switch(ctrl.action) {

View File

@ -18,7 +18,7 @@
<th width="10%">// 'name' | tr //</th>
<th width="18%">// 'description' | tr //</th>
<th width="18%">// 'destination' | tr //</th>
<th width="18%">// 'start_time' | tr //</th>
<th width="18%">// 'last_start_time' | tr //</th>
<th width="14%">// 'activation' | tr// </th>
<th width="15%">// 'actions' | tr //</th>
</thead>
@ -41,11 +41,11 @@
</td>
<td width="15%">
<div class="display-inline-block" ng-switch on="//r.enabled//">
<a href="javascript:void(0);" ng-click="vm.togglePolicy(r.id, 0)"><span ng-switch-when="1" class="glyphicon glyphicon-stop color-danger"></span></a>
<a href="javascript:void(0);" ng-click="vm.togglePolicy(r.id, 1)"><span ng-switch-when="0" class="glyphicon glyphicon-play color-success"></span></a>
<a href="javascript:void(0);" ng-click="vm.togglePolicy(r.id, 0)" title="// 'disabled' | tr //"><span ng-switch-when="1" class="glyphicon glyphicon-stop color-danger"></span></a>
<a href="javascript:void(0);" ng-click="vm.togglePolicy(r.id, 1)" title="// 'enabled' | tr //"><span ng-switch-when="0" class="glyphicon glyphicon-play color-success"></span></a>
</div>
&nbsp;
<a href="javascript:void(0);" data-toggle="modal" data-target="#createPolicyModal" ng-click="vm.editReplication(r.id)"><span class="glyphicon glyphicon-pencil"></span></a>
<a href="javascript:void(0);" data-toggle="modal" data-target="#createPolicyModal" ng-click="vm.editReplication(r.id)" title="// 'edit_policy' | tr //"><span class="glyphicon glyphicon-pencil"></span></a>
&nbsp;
<!--a href="javascript:void(0);"><span class="glyphicon glyphicon-trash"></span></a -->
</td>
@ -63,11 +63,11 @@
<div class="input-group">
<input type="text" class="form-control" placeholder="" ng-model="vm.replicationJobName" size="30">
<span class="input-group-btn">
<button class="btn btn-primary" type="button" ng-click="vm.searchReplicationJob()"><span class="glyphicon glyphicon-search"></span></button>
<button class="btn btn-primary" type="button" ng-click="vm.searchReplicationJob()" ng-disabled="vm.refreshPending"><span class="glyphicon glyphicon-search"></span></button>
</span>
</div>
<div class="input-group">
<button class="btn btn-success" ng-click="vm.searchReplicationJob()"><span class="glyphicon glyphicon-refresh"></span></button>
<button type="button" class="btn btn-success" ng-click="vm.searchReplicationJob()"><span class="glyphicon glyphicon-refresh"></span></button>
</div>
</div>
<div class="pane-split" id="down-pane">
@ -75,11 +75,12 @@
<div class="table-head-container">
<table class="table table-pane table-header">
<thead>
<th width="20%">// 'name' | tr //</th>
<th width="15%">// 'operation' | tr //</th>
<th width="20%">// 'start_time' | tr //</th>
<th width="20%">// 'end_time' | tr //</th>
<th width="15%">// 'status' | tr //</th>
<th width="15%">// 'name' | tr //</th>
<th width="12%">// 'operation' | tr //</th>
<th width="18%">// 'creation_time' | tr //</th>
<th width="18%">// 'start_time' | tr //</th>
<th width="18%">// 'end_time' | tr //</th>
<th width="9%">// 'status' | tr //</th>
<th width="10%">// 'logs' | tr //</th>
</thead>
</table>
@ -91,12 +92,13 @@
<td colspan="4" height="100%" class="empty-hint" ><h3 class="text-muted">// 'no_replication_jobs' | tr //</h3></td>
</tr>
<tr ng-if="vm.replicationJobs.length > 0" ng-repeat="r in vm.replicationJobs">
<td width="20%">//r.repository//</td>
<td width="15%">//r.operation//</td>
<td width="20%">//r.creation_time | dateL : 'YYYY-MM-DD HH:mm:ss'//</td>
<td width="20%">//r.update_time | dateL : 'YYYY-MM-DD HH:mm:ss'//</td>
<td width="15%">//r.status//</td>
<td width="10%"><a href="javascript:void(0);" ng-click="vm.downloadLog(r.id)"><span style="margin-left: 10px;" class="glyphicon glyphicon-file"></span></a></td>
<td width="15%">//r.repository//</td>
<td width="12%">//r.operation//</td>
<td width="18%">//r.creation_time | dateL : 'YYYY-MM-DD HH:mm:ss'//</td>
<td width="18%">//r.creation_time | dateL : 'YYYY-MM-DD HH:mm:ss'//</td>
<td width="18%">//r.update_time | dateL : 'YYYY-MM-DD HH:mm:ss'//</td>
<td width="9%">//r.status//</td>
<td width="10%" align="left"><a href="javascript:void(0);" ng-click="vm.downloadLog(r.id)" title="// 'download_log' | tr //"><span style="margin-left: 10px;" class="glyphicon glyphicon-file"></span></a></td>
</tr>
</tbody>
</table>

View File

@ -34,8 +34,10 @@
vm.projectId = getParameterByName('project_id', $location.absUrl());
vm.retrievePolicy();
vm.refreshPending = false;
function searchReplicationPolicy() {
vm.refreshPending = true;
vm.retrievePolicy();
}
@ -63,15 +65,17 @@
}
function listReplicationPolicyFailed(data, status) {
console.log('Failed list replication policy:' + data);
console.log('Failed list replication policy:' + data);
}
function listReplicationJobSuccess(data, status) {
vm.replicationJobs = data || [];
vm.refreshPending = false;
}
function listReplicationJobFailed(data, status) {
console.log('Failed list replication job:' + data);
vm.refreshPending = false;
}
function addReplication() {

View File

@ -20,7 +20,7 @@
<a role="button" data-toggle="collapse" data-parent="" href="?project_id=//vm.projectId//#collapse//$index + 1//" aria-expanded="true" aria-controls="collapse//$index+1//">
<span class="glyphicon glyphicon-book"></span> &nbsp;//repo// &nbsp;&nbsp;<span class="badge">//vm.tagCount[repo]//</span>
</a>
<a class="pull-right" style="margin-right: 78px;" href="javascript:void(0)" data-toggle="modal" data-target="#myModal" ng-click="vm.deleteByRepo(repo)"><span class="glyphicon glyphicon-trash"></span></a>
<a class="pull-right" style="margin-right: 78px;" href="javascript:void(0)" data-toggle="modal" data-target="#myModal" ng-click="vm.deleteByRepo(repo)" title="// 'delete_repo' | tr //"><span class="glyphicon glyphicon-trash"></span></a>
</h4>
</div>
<list-tag associate-id="$index + 1" repo-name="repo" tag-count="vm.tagCount"></list-tag>

View File

@ -33,6 +33,12 @@
vm.projectId = getParameterByName('project_id', $location.absUrl());
vm.retrieve();
$scope.$on('$locationChangeStart', function() {
console.log('triggered locationChangeStart....');
vm.projectId = getParameterByName('project_id', $location.absUrl());
vm.retrieve();
});
$scope.$on('$locationChangeSuccess', function() {
vm.projectId = getParameterByName('project_id', $location.absUrl());
vm.retrieve();

View File

@ -14,7 +14,7 @@
<td>
<pull-command repo-name="//vm.repoName//" tag="//tag//"></pull-command>
</td>
<td style="text-align: center;"><a href="javascript:void(0);" data-toggle="modal" data-target="#myModal" ng-click="vm.deleteByTag({repoName: vm.repoName, tag: tag})"><span class="glyphicon glyphicon-trash"></span></a></td>
<td style="text-align: center;"><a href="javascript:void(0);" data-toggle="modal" data-target="#myModal" ng-click="vm.deleteByTag({repoName: vm.repoName, tag: tag})" title="// 'delete_tag' | tr //"><span class="glyphicon glyphicon-trash"></span></a></td>
</tr>
</tbody>
</table>

View File

@ -3,7 +3,7 @@
<div class="input-group">
<input type="text" class="form-control" value="docker pull //vm.harborRegUrl////vm.repoName//://vm.tag//" readonly="readonly" size="60">
<div class="input-group-addon">
<a href="javascript:void(0);"><span class="glyphicon glyphicon-duplicate"></span></a>
<a href="javascript:void(0);" title="// 'select_all' | tr //"><span class="glyphicon glyphicon-duplicate"></span></a>
</div>
</div>
</div>

View File

@ -1,4 +1,4 @@
<h4 class="page-header title-color underlined">// 'summary' | tr //</h4>
<dl class="page-content dl-horizontal" ng-repeat="(key, value) in vm.statProjects">
<dt>// key | tr //:</dt><dd>//value//</dd>
</dl>
<dl class="page-content dl-horizontal" ng-repeat="(key, value) in vm.statProjects">
<dt>// key | tr //:</dt><dd>//value//<dd>
</dl>

View File

@ -1,4 +1,4 @@
<div class="modal fade" id="createDestinationModal" tabindex="-1" role="dialog">
<div class="modal fade" data-backdrop="static" id="createDestinationModal" tabindex="-1" role="dialog">
<div class="modal-dialog">
<form name="form" class="form-horizontal css-form" novalidate>
<div class="modal-content">
@ -41,7 +41,13 @@
<div class="form-group col-md-12 form-group-custom">
<div class="col-md-3"></div>
<div class="col-md-9">
<button type="submit" class="btn btn-default" ng-click="form.$valid && vm.pingDestination()">// 'test_connection' | tr //</button>
<button type="submit" class="btn btn-default" ng-disabled="vm.notAvailable || !vm.pingAvailable" ng-click="form.$valid && vm.pingDestination()">// 'test_connection' | tr //</button>
</div>
</div>
<div class="form-group col-md-12 form-group-custom">
<div class="col-md-3"></div>
<div class="col-md-9">
<span>// vm.pingMessage //</span>
</div>
</div>
</div>

View File

@ -21,6 +21,17 @@
vm.pingDestination = pingDestination;
vm.editable = true;
vm.notAvailable = true;
vm.pingAvailable = true;
vm.pingMessage = '';
$scope.$watch('destination.endpoint', function(current) {
if(current) {
vm.notAvailable = false;
}else{
vm.notAvailable = true;
}
});
function addNew() {
vm.editable = true;
@ -104,6 +115,8 @@
}
function pingDestination() {
vm.pingAvailable = false;
var target = {
'name': vm0.name,
'endpoint': vm0.endpoint,
@ -115,10 +128,12 @@
.error(pingDestinationFailed);
}
function pingDestinationSuccess(data, status) {
alert($filter('tr')('successful_ping_target', []));
vm.pingAvailable = true;
vm.pingMessage = $filter('tr')('successful_ping_target', []);
}
function pingDestinationFailed(data, status) {
alert($filter('tr')('failed_ping_target', []) + ':' + data);
vm.pingAvailable = true;
vm.pingMessage = $filter('tr')('failed_ping_target', []) + (data && data.length > 0 ? ':' + data : '.');
}
}
@ -145,6 +160,10 @@
scope.form.$setPristine();
scope.form.$setUntouched();
ctrl.notAvailble = true;
ctrl.pingAvailable = true;
ctrl.pingMessage = '';
switch(ctrl.action) {
case 'ADD_NEW':
ctrl.addNew();

View File

@ -54,7 +54,6 @@
function editReplication(policyId) {
vm.action = 'EDIT';
vm.modalTitle = 'Edit policy';
vm.policyId = policyId;
}
}

View File

@ -36,7 +36,7 @@
function filter(input, pattern) {
var d = new Date(input || '');
if(d.getTime() <= 0) return 'N/A';
if(d.getTime() <= 0) return '-';
return moment(d).format(pattern);
}
}

View File

@ -132,6 +132,7 @@ var locale_messages = {
'no_projects_add_new_project': 'No projects, add new project now.',
'no_repositories': 'No repositories found, please use "docker push" to upload images.',
'confirm_to_delete_member_title': 'Delete project member',
'failed_to_add_member': 'Project member can not be added, insuffient permissions.',
'failed_to_change_member': 'Project member can not be changed, insuffient permissions.',
'failed_to_delete_member': 'Project member can not be deleted, insuffient permissions.',
'confirm_to_change_member_title': 'Change project member',
@ -144,6 +145,7 @@ var locale_messages = {
'description': 'Description',
'destination': 'Destination',
'start_time': 'Start Time',
'last_start_time': 'Last Start Time',
'end_time': 'End Time',
'activation': 'Activation',
'replication_jobs': 'Replication Jobs',
@ -184,13 +186,19 @@ var locale_messages = {
'successful_added': 'Added new user successfully.',
'copyright': 'Copyright',
'all_rights_reserved': 'All Rights Reserved.',
'successful_ping_target': 'Successful Ping target.',
'failed_ping_target': 'Failed to Ping target:',
'successful_ping_target': 'Test connection successfully.',
'failed_ping_target': 'Faild to connect target',
'policy_already_exists': 'Policy alreay exists.',
'failed_update_policy': 'Failed update policy:',
'destination_already_exists': 'Destination already exists.',
'failed_delete_destination': 'Delete destination failed:',
'failed_create_destination': 'Create destination failed:',
'failed_update_destination': 'Failed update destination:',
'refresh': 'Refresh'
'refresh': 'Refresh',
'select_all': 'Select All',
'delete_tag': 'Delete Tag',
'delete_repo': 'Delete Repo',
'download_log': 'Download Logs',
'edit': 'Edit',
'delete': 'Delete'
};

View File

@ -130,6 +130,7 @@ var locale_messages = {
'no_projects_add_new_project': '当前没有项目,请新增项目。',
'no_repositories': '未发现镜像,请用"docker push"命令上传镜像。',
'confirm_to_delete_member_title': '删除项目成员',
'failed_to_add_member': '无法添加项目成员,权限不足。',
'failed_to_change_member': '无法修改项目成员,权限不足。',
'failed_to_delete_member': '无法删除项目成员,权限不足。',
'confirm_to_change_member_title': '修改项目成员',
@ -142,6 +143,7 @@ var locale_messages = {
'description': '描述',
'destination': '目标',
'start_time': '起始时间',
'last_start_time': '上次起始时间',
'end_time': '结束时间',
'activation': '活动状态',
'replication_jobs': '复制任务',
@ -183,13 +185,19 @@ var locale_messages = {
'successful_added': '新增用户成功。',
'copyright': '版权所有',
'all_rights_reserved': '保留所有权利。',
'successful_ping_target': 'Ping 目标成功。',
'failed_ping_target': 'Ping 目标失败:',
'successful_ping_target': '测试连接目标成功。',
'failed_ping_target': '测试连接目标失败',
'policy_already_exists': '策略已存在。',
'failed_update_policy': '修改策略失败:',
'destination_already_exists': '目标已存在。',
'failed_delete_destination': '删除目标失败:',
'failed_create_destination': '创建目标失败:',
'failed_update_destination': '修改目标失败:',
'refresh': '刷新'
'refresh': '刷新',
'select_all': '全选',
'delete_tag': '删除镜像标签',
'delete_repo': '删除镜像仓库',
'download_log': '下载日志',
'edit': '修改',
'delete': '删除'
};