mirror of
https://github.com/goharbor/harbor.git
synced 2025-01-22 23:51:27 +01:00
Merge pull request #1827 from wknet123/dev-revised
Updates for showing image ID and router tags.
This commit is contained in:
commit
79263a8ba7
@ -44,6 +44,7 @@ func initRouters() {
|
||||
beego.Router("/harbor/projects/:id/replication", &controllers.IndexController{})
|
||||
beego.Router("/harbor/projects/:id/member", &controllers.IndexController{})
|
||||
beego.Router("/harbor/projects/:id/log", &controllers.IndexController{})
|
||||
beego.Router("/harbor/tags/:id/*", &controllers.IndexController{})
|
||||
|
||||
beego.Router("/harbor/users", &controllers.IndexController{})
|
||||
beego.Router("/harbor/logs", &controllers.IndexController{})
|
||||
|
@ -10,7 +10,7 @@
|
||||
top: 60px;
|
||||
left: 0px;
|
||||
padding-left: 36px;
|
||||
padding-right: 24px;
|
||||
padding-right: 36px;
|
||||
}
|
||||
|
||||
.search-header {
|
||||
|
@ -9,4 +9,8 @@
|
||||
.start-content-padding {
|
||||
padding: 0px !important;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.content-area-override {
|
||||
padding: 24px 36px !important;
|
||||
}
|
@ -2,27 +2,27 @@
|
||||
<global-message [isAppLevel]="true"></global-message>
|
||||
<navigator (showAccountSettingsModal)="openModal($event)" (showPwdChangeModal)="openModal($event)"></navigator>
|
||||
<div class="content-container">
|
||||
<div class="content-area" [class.container-override]="showSearch" [class.start-content-padding]="shouldOverrideContent">
|
||||
<global-message [isAppLevel]="false"></global-message>
|
||||
<!-- Only appear when searching -->
|
||||
<search-result></search-result>
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
<nav class="sidenav" *ngIf="isUserExisting">
|
||||
<section class="sidenav-content">
|
||||
<a routerLink="/harbor/projects" routerLinkActive="active" class="nav-link">{{'SIDE_NAV.PROJECTS' | translate}}</a>
|
||||
<a routerLink="/harbor/logs" routerLinkActive="active" class="nav-link" style="margin-top: 4px;">{{'SIDE_NAV.LOGS' | translate}}</a>
|
||||
<section class="nav-group collapsible" *ngIf="isSystemAdmin" style="margin-top: 4px;">
|
||||
<input id="tabsystem" type="checkbox">
|
||||
<label for="tabsystem">{{'SIDE_NAV.SYSTEM_MGMT.NAME' | translate}}</label>
|
||||
<ul class="nav-list">
|
||||
<li><a class="nav-link" routerLink="/harbor/users" routerLinkActive="active">{{'SIDE_NAV.SYSTEM_MGMT.USER' | translate}}</a></li>
|
||||
<li><a class="nav-link" routerLink="/harbor/replications/endpoints" routerLinkActive="active">{{'SIDE_NAV.SYSTEM_MGMT.REPLICATION' | translate}}</a></li>
|
||||
<li><a class="nav-link" routerLink="/harbor/configs" routerLinkActive="active">{{'SIDE_NAV.SYSTEM_MGMT.CONFIG' | translate}}</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
</section>
|
||||
</nav>
|
||||
<div class="content-area" [class.container-override]="showSearch" [class.content-area-override]="!shouldOverrideContent" [class.start-content-padding]="shouldOverrideContent">
|
||||
<global-message [isAppLevel]="false"></global-message>
|
||||
<!-- Only appear when searching -->
|
||||
<search-result></search-result>
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
<nav class="sidenav" style="padding: 12px 36px;" *ngIf="isUserExisting">
|
||||
<section class="sidenav-content">
|
||||
<a routerLink="/harbor/projects" routerLinkActive="active" class="nav-link">{{'SIDE_NAV.PROJECTS' | translate}}</a>
|
||||
<a routerLink="/harbor/logs" routerLinkActive="active" class="nav-link" style="margin-top: 4px;">{{'SIDE_NAV.LOGS' | translate}}</a>
|
||||
<section class="nav-group collapsible" *ngIf="isSystemAdmin" style="margin-top: 4px;">
|
||||
<input id="tabsystem" type="checkbox">
|
||||
<label for="tabsystem">{{'SIDE_NAV.SYSTEM_MGMT.NAME' | translate}}</label>
|
||||
<ul class="nav-list">
|
||||
<li><a class="nav-link" routerLink="/harbor/users" routerLinkActive="active">{{'SIDE_NAV.SYSTEM_MGMT.USER' | translate}}</a></li>
|
||||
<li><a class="nav-link" routerLink="/harbor/replications/endpoints" routerLinkActive="active">{{'SIDE_NAV.SYSTEM_MGMT.REPLICATION' | translate}}</a></li>
|
||||
<li><a class="nav-link" routerLink="/harbor/configs" routerLinkActive="active">{{'SIDE_NAV.SYSTEM_MGMT.CONFIG' | translate}}</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
</section>
|
||||
</nav>
|
||||
</div>
|
||||
</clr-main-container>
|
||||
<account-settings-modal></account-settings-modal>
|
||||
|
@ -1,7 +1,3 @@
|
||||
.custom-h2 {
|
||||
margin-top: 0px !important;
|
||||
}
|
||||
|
||||
.config-container {
|
||||
margin-left: 24px;
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
<div class="config-container">
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
|
||||
<h2 style="display: inline-block;" class="custom-h2">{{'CONFIG.TITLE' | translate }}</h2>
|
||||
<span class="spinner spinner-inline" [hidden]="inProgress === false"></span>
|
||||
<ul id="configTabs" class="nav" role="tablist">
|
||||
@ -66,4 +67,5 @@
|
||||
<button type="button" class="btn btn-outline" (click)="testLDAPServer()" *ngIf="showLdapServerBtn" [disabled]="!isLDAPConfigValid()">{{'BUTTON.TEST_LDAP' | translate}}</button>
|
||||
<span class="spinner spinner-inline" [hidden]="!testingInProgress"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,4 +1,4 @@
|
||||
<div class="row" style="margin-right: 12px;">
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
|
||||
<h2 class="header-title">{{'PROJECT.PROJECTS' | translate}}</h2>
|
||||
<div>
|
||||
|
@ -2,12 +2,19 @@
|
||||
<h3 class="modal-title">{{modalTitle}}</h3>
|
||||
<inline-alert class="modal-title" (confirmEvt)="confirmCancel($event)"></inline-alert>
|
||||
<div class="modal-body">
|
||||
<div class="alert alert-danger" *ngIf="!editable">
|
||||
<div class="alert-item">
|
||||
<span class="alert-text">
|
||||
{{'DESTINATION.CANNOT_EDIT' | translate}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<form #targetForm="ngForm">
|
||||
<section class="form-block">
|
||||
<div class="form-group">
|
||||
<label for="destination_name" class="col-md-4 form-group-label-override">{{ 'DESTINATION.NAME' | translate }}<span style="color: red">*</span></label>
|
||||
<label class="col-md-8" for="destination_name" aria-haspopup="true" role="tooltip" [class.invalid]="targetName.errors && (targetName.dirty || targetName.touched)" [class.valid]="targetName.valid" class="tooltip tooltip-validation tooltip-sm tooltip-bottom-right">
|
||||
<input type="text" id="destination_name" [disabled]="testOngoing" [(ngModel)]="target.name" name="targetName" size="20" #targetName="ngModel" value="" required>
|
||||
<input type="text" id="destination_name" [disabled]="testOngoing || !editable" [(ngModel)]="target.name" name="targetName" size="20" #targetName="ngModel" value="" required>
|
||||
<span class="tooltip-content" *ngIf="targetName.errors && targetName.errors.required && (targetName.dirty || targetName.touched)">
|
||||
{{ 'DESTINATION.NAME_IS_REQUIRED' | translate }}
|
||||
</span>
|
||||
@ -16,7 +23,7 @@
|
||||
<div class="form-group">
|
||||
<label for="destination_url" class="col-md-4 form-group-label-override">{{ 'DESTINATION.URL' | translate }}<span style="color: red">*</span></label>
|
||||
<label class="col-md-8" for="destination_url" aria-haspopup="true" role="tooltip" [class.invalid]="targetEndpoint.errors && (targetEndpoint.dirty || targetEndpoint.touched)" [class.valid]="targetEndpoint.valid" class="tooltip tooltip-validation tooltip-sm tooltip-bottom-right">
|
||||
<input type="text" id="destination_url" [disabled]="testOngoing" [(ngModel)]="target.endpoint" size="20" name="endpointUrl" #targetEndpoint="ngModel" required>
|
||||
<input type="text" id="destination_url" [disabled]="testOngoing || !editable" [(ngModel)]="target.endpoint" size="20" name="endpointUrl" #targetEndpoint="ngModel" required>
|
||||
<span class="tooltip-content" *ngIf="targetEndpoint.errors && targetEndpoint.errors.required && (targetEndpoint.dirty || targetEndpoint.touched)">
|
||||
{{ 'DESTINATION.URL_IS_REQUIRED' | translate }}
|
||||
</span>
|
||||
@ -24,11 +31,11 @@
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="destination_username" class="col-md-4 form-group-label-override">{{ 'DESTINATION.USERNAME' | translate }}</label>
|
||||
<input type="text" class="col-md-8" id="destination_username" [disabled]="testOngoing" [(ngModel)]="target.username" size="20" name="username" #username="ngModel">
|
||||
<input type="text" class="col-md-8" id="destination_username" [disabled]="testOngoing || !editable" [(ngModel)]="target.username" size="20" name="username" #username="ngModel">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="destination_password" class="col-md-4 form-group-label-override">{{ 'DESTINATION.PASSWORD' | translate }}</label>
|
||||
<input type="password" class="col-md-8" id="destination_password" [disabled]="testOngoing" [(ngModel)]="target.password" size="20" name="password" #password="ngModel">
|
||||
<input type="password" class="col-md-8" id="destination_password" [disabled]="testOngoing || !editable" [(ngModel)]="target.password" size="20" name="password" #password="ngModel">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="spin" class="col-md-4"></label>
|
||||
@ -41,6 +48,6 @@
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline" (click)="testConnection()" [disabled]="testOngoing || targetEndpoint.errors">{{ 'DESTINATION.TEST_CONNECTION' | translate }}</button>
|
||||
<button type="button" class="btn btn-outline" (click)="onCancel()" [disabled]="testOngoing">{{ 'BUTTON.CANCEL' | translate }}</button>
|
||||
<button type="submit" class="btn btn-primary" [disabled]="!targetForm.form.valid" (click)="onSubmit()" [disabled]="testOngoing">{{ 'BUTTON.OK' | translate }}</button>
|
||||
<button type="submit" class="btn btn-primary" (click)="onSubmit()" [disabled]="testOngoing || targetForm.form.invalid || !editable">{{ 'BUTTON.OK' | translate }}</button>
|
||||
</div>
|
||||
</clr-modal>
|
@ -20,6 +20,8 @@ export class CreateEditDestinationComponent implements AfterViewChecked {
|
||||
modalTitle: string;
|
||||
createEditDestinationOpened: boolean;
|
||||
|
||||
editable: boolean;
|
||||
|
||||
testOngoing: boolean;
|
||||
pingTestMessage: string;
|
||||
pingStatus: boolean;
|
||||
@ -49,10 +51,12 @@ export class CreateEditDestinationComponent implements AfterViewChecked {
|
||||
private messageHandlerService: MessageHandlerService,
|
||||
private translateService: TranslateService) {}
|
||||
|
||||
openCreateEditTarget(targetId?: number) {
|
||||
openCreateEditTarget(editable: boolean, targetId?: number) {
|
||||
|
||||
this.target = new Target();
|
||||
this.createEditDestinationOpened = true;
|
||||
|
||||
this.editable = editable;
|
||||
|
||||
this.hasChanged = false;
|
||||
|
||||
this.pingTestMessage = '';
|
||||
|
@ -87,13 +87,31 @@ export class DestinationComponent implements OnInit {
|
||||
}
|
||||
|
||||
openModal() {
|
||||
this.createEditDestinationComponent.openCreateEditTarget();
|
||||
this.createEditDestinationComponent.openCreateEditTarget(true);
|
||||
this.target = new Target();
|
||||
}
|
||||
|
||||
editTarget(target: Target) {
|
||||
if (target) {
|
||||
this.createEditDestinationComponent.openCreateEditTarget(target.id);
|
||||
let editable = true;
|
||||
this.replicationService
|
||||
.listTargetPolicies(target.id)
|
||||
.subscribe(
|
||||
policies=>{
|
||||
if(policies && policies.length > 0) {
|
||||
for(let i = 0; i < policies.length; i++){
|
||||
let p = policies[i];
|
||||
if(p.enabled === 1) {
|
||||
editable = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.createEditDestinationComponent.openCreateEditTarget(editable, target.id);
|
||||
},
|
||||
error=>this.messageHandlerService.handleError(error)
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,6 +122,14 @@ export class ReplicationService {
|
||||
.catch(error=>Observable.throw(error));
|
||||
}
|
||||
|
||||
listTargetPolicies(targetId: number): Observable<Policy[]> {
|
||||
console.log('List target with policy.');
|
||||
return this.http
|
||||
.get(`/api/targets/${targetId}/policies`)
|
||||
.map(response=>response.json() as Policy[])
|
||||
.catch(error=>Observable.throw(error));
|
||||
}
|
||||
|
||||
getTarget(targetId: number): Observable<Target> {
|
||||
console.log('Get target by ID:' + targetId);
|
||||
return this.http
|
||||
|
@ -4,8 +4,6 @@
|
||||
<clr-dg-column>{{'REPOSITORY.PULL_COUNT' | translate}}</clr-dg-column>
|
||||
<clr-dg-row *ngFor="let r of repositories" [clrDgItem]='r'>
|
||||
<clr-dg-action-overflow [hidden]="!hasProjectAdminRole">
|
||||
<button class="action-item">{{'REPOSITORY.COPY_ID' | translate}}</button>
|
||||
<button class="action-item">{{'REPOSITORY.COPY_PARENT_ID' | translate}}</button>
|
||||
<button class="action-item" (click)="deleteRepo(r.name)">{{'REPOSITORY.DELETE' | translate}}</button>
|
||||
</clr-dg-action-overflow>
|
||||
<clr-dg-cell><a href="javascript:void(0)" (click)="gotoLink(projectId || r.project_id, r.name || r.repository_name)">{{r.name || r.repository_name}}</a></clr-dg-cell>
|
||||
|
@ -1,6 +1,19 @@
|
||||
|
||||
<a *ngIf="hasSignedIn" [routerLink]="['/harbor', 'projects', projectId, 'repository']">< {{'REPOSITORY.REPOSITORIES' | translate}}</a>
|
||||
<a *ngIf="!hasSignedIn" [routerLink]="['/harbor', 'sign-in']">< {{'SEARCH.BACK' | translate}}</a>
|
||||
|
||||
<clr-modal [(clrModalOpen)]="showTagManifestOpened" [clrModalStaticBackdrop]="staticBackdrop" [clrModalClosable]="closable">
|
||||
<h3 class="modal-title">{{ manifestInfoTitle | translate }}</h3>
|
||||
<div class="modal-body">
|
||||
<div class="row col-md-12">
|
||||
<textarea rows="3" (click)="selectAndCopy($event)">{{tagID}}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" (click)="showTagManifestOpened = false">{{'BUTTON.OK' | translate}}</button>
|
||||
</div>
|
||||
</clr-modal>
|
||||
|
||||
<h2 class="sub-header-title">{{repoName}} <span class="badge">{{tags ? tags.length : 0}}</span></h2>
|
||||
<clr-datagrid>
|
||||
<clr-dg-column>{{'REPOSITORY.TAG' | translate}}</clr-dg-column>
|
||||
@ -12,8 +25,10 @@
|
||||
<clr-dg-column>{{'REPOSITORY.ARCHITECTURE' | translate}}</clr-dg-column>
|
||||
<clr-dg-column>{{'REPOSITORY.OS' | translate}}</clr-dg-column>
|
||||
<clr-dg-row *ngFor="let t of tags" [clrDgItem]='t'>
|
||||
<clr-dg-action-overflow *ngIf="hasProjectAdminRole">
|
||||
<button class="action-item" (click)="deleteTag(t)">{{'REPOSITORY.DELETE' | translate}}</button>
|
||||
<clr-dg-action-overflow>
|
||||
<button class="action-item" (click)="showTagID('tag', t)">{{'REPOSITORY.COPY_ID' | translate}}</button>
|
||||
<button class="action-item" (click)="showTagID('parent', t)">{{'REPOSITORY.COPY_PARENT_ID' | translate}}</button>
|
||||
<button class="action-item" [hidden]="!hasProjectAdminRole" (click)="deleteTag(t)">{{'REPOSITORY.DELETE' | translate}}</button>
|
||||
</clr-dg-action-overflow>
|
||||
<clr-dg-cell>{{t.tag}}</clr-dg-cell>
|
||||
<clr-dg-cell>{{t.pullCommand}}</clr-dg-cell>
|
||||
|
@ -37,6 +37,14 @@ export class TagRepositoryComponent implements OnInit, OnDestroy {
|
||||
|
||||
hasSignedIn: boolean;
|
||||
|
||||
showTagManifestOpened: boolean;
|
||||
manifestInfoTitle: string;
|
||||
tagID: string;
|
||||
staticBackdrop: boolean = true;
|
||||
closable: boolean = false;
|
||||
|
||||
selectAll: boolean = false;
|
||||
|
||||
private subscription: Subscription;
|
||||
|
||||
constructor(
|
||||
@ -123,6 +131,8 @@ export class TagRepositoryComponent implements OnInit, OnDestroy {
|
||||
tag.dockerVersion = data['docker_version'];
|
||||
tag.pullCommand = 'docker pull ' + this.registryUrl + '/' + t.manifest.name + ':' + t.tag;
|
||||
tag.os = data['os'];
|
||||
tag.id = data['id'];
|
||||
tag.parent = data['parent'];
|
||||
this.tags.push(tag);
|
||||
});
|
||||
}
|
||||
@ -149,4 +159,19 @@ export class TagRepositoryComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
showTagID(type: string, tag: TagView) {
|
||||
if(tag) {
|
||||
if(type === 'tag') {
|
||||
this.manifestInfoTitle = 'REPOSITORY.COPY_ID';
|
||||
this.tagID = tag.id;
|
||||
} else if(type === 'parent') {
|
||||
this.manifestInfoTitle = 'REPOSITORY.COPY_PARENT_ID';
|
||||
this.tagID = tag.parent;
|
||||
}
|
||||
this.showTagManifestOpened = true;
|
||||
}
|
||||
}
|
||||
selectAndCopy($event) {
|
||||
$event.target.select();
|
||||
}
|
||||
}
|
@ -7,4 +7,6 @@ export class TagView {
|
||||
dockerVersion: string;
|
||||
architecture: string;
|
||||
os: string;
|
||||
id: string;
|
||||
parent: string;
|
||||
}
|
@ -4,6 +4,13 @@
|
||||
<div class="modal-body">
|
||||
<form #policyForm="ngForm">
|
||||
<section class="form-block">
|
||||
<div class="alert alert-danger" *ngIf="readonly">
|
||||
<div class="alert-item">
|
||||
<span class="alert-text">
|
||||
{{'REPLICATION.CANNOT_EDIT' | translate}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="policy_name" class="col-md-4 form-group-label-override">{{'REPLICATION.NAME' | translate}}<span style="color: red">*</span></label>
|
||||
<label for="policy_name" class="col-md-8" aria-haspopup="true" role="tooltip" [class.invalid]="name.errors && (name.dirty || name.touched)" [class.valid]="name.valid" class="tooltip tooltip-validation tooltip-sm tooltip-bottom-right">
|
||||
|
@ -27,6 +27,7 @@ export const errorHandler = function (error: any): string {
|
||||
case 404:
|
||||
return "NOT_FOUND_ERROR";
|
||||
case 412:
|
||||
return "PRECONDITION_FAILED";
|
||||
case 409:
|
||||
return "CONFLICT_ERROR";
|
||||
case 500:
|
||||
|
@ -21,7 +21,6 @@
|
||||
|
||||
.action-panel-pos {
|
||||
position: relative;
|
||||
top: 6px;
|
||||
padding-left: 12px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
@ -1,35 +1,37 @@
|
||||
<div style="margin-left: 24px;">
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
|
||||
<h2 class="custom-h2">{{'SIDE_NAV.SYSTEM_MGMT.USER' | translate}}</h2>
|
||||
<div class="action-panel-pos">
|
||||
<span>
|
||||
<button *ngIf="canCreateUser" type="submit" class="btn btn-primary custom-add-button" (click)="addNewUser()"><clr-icon shape="add"></clr-icon> {{'USER.ADD_ACTION' | translate}}</button>
|
||||
</span>
|
||||
<grid-filter class="filter-pos" filterPlaceholder='{{"USER.FILTER_PLACEHOLDER" | translate}}' (filter)="doFilter($event)"></grid-filter>
|
||||
<span class="refresh-btn" (click)="refreshUser()">
|
||||
<clr-icon shape="refresh" [hidden]="inProgress" ng-disabled="inProgress"></clr-icon>
|
||||
<span class="spinner spinner-inline" [hidden]="inProgress === false"></span>
|
||||
</span>
|
||||
<span>
|
||||
<button *ngIf="canCreateUser" type="submit" class="btn btn-primary custom-add-button" (click)="addNewUser()"><clr-icon shape="add"></clr-icon> {{'USER.ADD_ACTION' | translate}}</button>
|
||||
</span>
|
||||
<grid-filter class="filter-pos" filterPlaceholder='{{"USER.FILTER_PLACEHOLDER" | translate}}' (filter)="doFilter($event)"></grid-filter>
|
||||
<span class="refresh-btn" (click)="refreshUser()">
|
||||
<clr-icon shape="refresh" [hidden]="inProgress" ng-disabled="inProgress"></clr-icon>
|
||||
<span class="spinner spinner-inline" [hidden]="inProgress === false"></span>
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<clr-datagrid>
|
||||
<clr-dg-column>{{'USER.COLUMN_NAME' | translate}}</clr-dg-column>
|
||||
<clr-dg-column>{{'USER.COLUMN_ADMIN' | translate}}</clr-dg-column>
|
||||
<clr-dg-column>{{'USER.COLUMN_EMAIL' | translate}}</clr-dg-column>
|
||||
<clr-dg-column>{{'USER.COLUMN_REG_NAME' | translate}}</clr-dg-column>
|
||||
<clr-dg-row *ngFor="let user of users" [clrDgItem]="user">
|
||||
<clr-dg-action-overflow [hidden]="isMySelf(user.user_id)">
|
||||
<button class="action-item" (click)="changeAdminRole(user)">{{adminActions(user)}}</button>
|
||||
<button class="action-item" (click)="deleteUser(user)">{{'USER.DEL_ACTION' | translate}}</button>
|
||||
</clr-dg-action-overflow>
|
||||
<clr-dg-cell>{{user.username}}</clr-dg-cell>
|
||||
<clr-dg-cell>{{isSystemAdmin(user)}}</clr-dg-cell>
|
||||
<clr-dg-cell>{{user.email}}</clr-dg-cell>
|
||||
<clr-dg-cell>
|
||||
{{user.creation_time}}
|
||||
</clr-dg-cell>
|
||||
</clr-dg-row>
|
||||
<clr-dg-footer>{{users.length}} {{'USER.ADD_ACTION' | translate}}</clr-dg-footer>
|
||||
</clr-datagrid>
|
||||
<clr-datagrid>
|
||||
<clr-dg-column>{{'USER.COLUMN_NAME' | translate}}</clr-dg-column>
|
||||
<clr-dg-column>{{'USER.COLUMN_ADMIN' | translate}}</clr-dg-column>
|
||||
<clr-dg-column>{{'USER.COLUMN_EMAIL' | translate}}</clr-dg-column>
|
||||
<clr-dg-column>{{'USER.COLUMN_REG_NAME' | translate}}</clr-dg-column>
|
||||
<clr-dg-row *ngFor="let user of users" [clrDgItem]="user">
|
||||
<clr-dg-action-overflow [hidden]="isMySelf(user.user_id)">
|
||||
<button class="action-item" (click)="changeAdminRole(user)">{{adminActions(user)}}</button>
|
||||
<button class="action-item" (click)="deleteUser(user)">{{'USER.DEL_ACTION' | translate}}</button>
|
||||
</clr-dg-action-overflow>
|
||||
<clr-dg-cell>{{user.username}}</clr-dg-cell>
|
||||
<clr-dg-cell>{{isSystemAdmin(user)}}</clr-dg-cell>
|
||||
<clr-dg-cell>{{user.email}}</clr-dg-cell>
|
||||
<clr-dg-cell>
|
||||
{{user.creation_time}}
|
||||
</clr-dg-cell>
|
||||
</clr-dg-row>
|
||||
<clr-dg-footer>{{users.length}} {{'USER.ADD_ACTION' | translate}}</clr-dg-footer>
|
||||
</clr-datagrid>
|
||||
</div>
|
||||
<new-user-modal (addNew)="addUserToList($event)"></new-user-modal>
|
||||
</div>
|
||||
</div>
|
@ -255,7 +255,8 @@
|
||||
"UPDATED_SUCCESS": "Updated replication rule successfully.",
|
||||
"DELETED_SUCCESS": "Deleted replication rule successfully.",
|
||||
"DELETED_FAILED": "Deleted replication rule failed.",
|
||||
"TOGGLED_SUCCESS": "Toggled replication rule status successfully."
|
||||
"TOGGLED_SUCCESS": "Toggled replication rule status successfully.",
|
||||
"CANNOT_EDIT": "Replication rule cannot be changed while it is enabled."
|
||||
},
|
||||
"DESTINATION": {
|
||||
"NEW_ENDPOINT": "New Endpoint",
|
||||
@ -281,7 +282,8 @@
|
||||
"CREATED_SUCCESS": "Created endpoint successfully.",
|
||||
"UPDATED_SUCCESS": "Updated endpoint successfully.",
|
||||
"DELETED_SUCCESS": "Deleted endpoint successfully.",
|
||||
"DELETED_FAILED": "Deleted endpoint failed."
|
||||
"DELETED_FAILED": "Deleted endpoint failed.",
|
||||
"CANNOT_EDIT": "Endpoint cannot be changed while the replication rule is enabled."
|
||||
},
|
||||
"REPOSITORY": {
|
||||
"COPY_ID": "Copy ID",
|
||||
@ -312,7 +314,8 @@
|
||||
"ITEMS": "item(s)",
|
||||
"POP_REPOS": "Popular Repositories",
|
||||
"DELETED_REPO_SUCCESS": "Deleted repository successfully.",
|
||||
"DELETED_TAG_SUCCESS": "Deleted tag successfully."
|
||||
"DELETED_TAG_SUCCESS": "Deleted tag successfully.",
|
||||
"COPY": "Copy"
|
||||
},
|
||||
"ALERT": {
|
||||
"FORM_CHANGE_CONFIRMATION": "Some changes are not saved yet, do you really want to cancel?"
|
||||
@ -421,6 +424,7 @@
|
||||
"BAD_REQUEST_ERROR": "We are unable to perform your action because of a bad request",
|
||||
"NOT_FOUND_ERROR": "Your request can not be completed because the object does not exist",
|
||||
"CONFLICT_ERROR": "We are unable to perform your action because your submission has conflicts",
|
||||
"PRECONDITION_FAILED": "We are unable to perform your action because of a precondition failure.",
|
||||
"SERVER_ERROR": "We are unable to perform your action because internal server errors have occurred",
|
||||
"INCONRRECT_OLD_PWD": "The old password is incorrect",
|
||||
"UNKNOWN": "n/a"
|
||||
|
@ -255,7 +255,8 @@
|
||||
"UPDATED_SUCCESS": "更新复制策略成功。",
|
||||
"DELETED_SUCCESS": "删除复制策略成功。",
|
||||
"DELETED_FAILED": "删除复制策略失败。",
|
||||
"TOGGLED_SUCCESS": "切换复制策略状态成功。"
|
||||
"TOGGLED_SUCCESS": "切换复制策略状态成功。",
|
||||
"CANNOT_EDIT": "当复制规则启用时无法修改。"
|
||||
},
|
||||
"DESTINATION": {
|
||||
"NEW_ENDPOINT": "新建目标",
|
||||
@ -281,7 +282,8 @@
|
||||
"CREATED_SUCCESS": "创建目标成功。",
|
||||
"UPDATED_SUCCESS": "更新目标成功。",
|
||||
"DELETED_SUCCESS": "删除目标成功。",
|
||||
"DELETED_FAILED": "删除目标失败。"
|
||||
"DELETED_FAILED": "删除目标失败。",
|
||||
"CANNOT_EDIT": "当复制规则启用时目标无法修改。"
|
||||
},
|
||||
"REPOSITORY": {
|
||||
"COPY_ID": "复制ID",
|
||||
@ -312,7 +314,8 @@
|
||||
"ITEMS": "条记录",
|
||||
"POP_REPOS": "受欢迎的镜像库",
|
||||
"DELETED_REPO_SUCCESS": "删除镜像仓库成功。",
|
||||
"DELETED_TAG_SUCCESS": "删除镜像标签成功。"
|
||||
"DELETED_TAG_SUCCESS": "删除镜像标签成功。",
|
||||
"COPY": "复制"
|
||||
},
|
||||
"ALERT": {
|
||||
"FORM_CHANGE_CONFIRMATION": "表单内容改变,确认取消?"
|
||||
@ -421,6 +424,7 @@
|
||||
"BAD_REQUEST_ERROR": "错误请求导致无法完成操作",
|
||||
"NOT_FOUND_ERROR": "对象不存在故无法完成你的请求",
|
||||
"CONFLICT_ERROR": "你的提交包含冲突故操作无法完成",
|
||||
"PRECONDITION_FAILED": "由于前置条件包含冲突导致无法执行提交操作。",
|
||||
"SERVER_ERROR": "服务器出现内部错误,请求无法完成",
|
||||
"INCONRRECT_OLD_PWD": "旧密码不正确",
|
||||
"UNKNOWN": "n/a"
|
||||
|
Loading…
Reference in New Issue
Block a user