From 5619e4e7e3d9a880fccc48d5ee8b0b83e68814d1 Mon Sep 17 00:00:00 2001 From: kunw Date: Fri, 24 Feb 2017 18:06:08 +0800 Subject: [PATCH] Added lastest UI codes. --- .../account-settings-modal.component.html | 18 ++- .../account-settings-modal.component.ts | 15 +- .../src/app/account/account.module.ts | 4 +- .../password/password-setting.component.ts | 8 +- .../account/sign-in/sign-in.component.html | 3 +- src/clarity-seed/src/app/app.module.ts | 3 +- .../src/app/base/base-routing.module.ts | 8 ++ src/clarity-seed/src/app/base/base.module.ts | 4 +- .../harbor-shell/harbor-shell.component.html | 4 +- .../harbor-shell/harbor-shell.component.ts | 7 - .../base/navigator/navigator.component.html | 28 ++-- .../app/base/navigator/navigator.component.ts | 15 +- .../src/app/log/audit-log.component.html | 34 ++++- .../src/app/log/audit-log.component.ts | 132 +++++++++++++++++- src/clarity-seed/src/app/log/audit-log.css | 3 + .../src/app/log/audit-log.service.ts | 35 +++++ src/clarity-seed/src/app/log/audit-log.ts | 29 +++- src/clarity-seed/src/app/log/log.module.ts | 3 +- .../create-project.component.ts | 6 +- .../filter-project.component.html | 9 -- .../filter-project.component.ts | 23 --- .../list-project/list-project.component.html | 7 +- .../list-project/list-project.component.ts | 48 +------ .../app/project/member/member.component.html | 8 +- .../app/project/member/member.component.ts | 9 +- .../project-detail.component.html | 2 +- .../project-detail.component.ts | 12 +- .../project-routing-resolver.service.ts | 25 ++++ .../src/app/project/project-routing.module.ts | 10 +- .../src/app/project/project.component.html | 22 ++- .../src/app/project/project.component.ts | 103 +++++++++----- .../src/app/project/project.module.ts | 11 +- .../src/app/project/project.service.ts | 8 ++ src/clarity-seed/src/app/project/project.ts | 1 - .../search-project.component.html | 1 - .../search-project.component.ts | 13 -- .../app/shared/filter/filter.component.css | 4 + .../app/shared/filter/filter.component.html | 4 + .../src/app/shared/filter/filter.component.ts | 43 ++++++ .../harbor-action-overflow.html | 10 ++ .../harbor-action-overflow.ts | 9 ++ .../app/shared/max-length-ext.directive.ts | 5 +- .../src/app/shared/shared.module.ts | 16 ++- .../src/app/user/new-user-form.component.html | 72 ++++++++++ .../src/app/user/new-user-form.component.ts | 52 +++++++ .../app/user/new-user-modal.component.html | 19 +++ .../src/app/user/new-user-modal.component.ts | 106 ++++++++++++++ .../src/app/user/user.component.css | 32 +++++ .../src/app/user/user.component.html | 37 +++++ .../src/app/user/user.component.ts | 120 +++++++++++++++- src/clarity-seed/src/app/user/user.module.ts | 10 +- src/clarity-seed/src/app/user/user.service.ts | 59 ++++++++ src/clarity-seed/src/app/user/user.ts | 15 ++ 53 files changed, 1044 insertions(+), 240 deletions(-) create mode 100644 src/clarity-seed/src/app/log/audit-log.css create mode 100644 src/clarity-seed/src/app/log/audit-log.service.ts delete mode 100644 src/clarity-seed/src/app/project/filter-project/filter-project.component.html delete mode 100644 src/clarity-seed/src/app/project/filter-project/filter-project.component.ts create mode 100644 src/clarity-seed/src/app/project/project-routing-resolver.service.ts delete mode 100644 src/clarity-seed/src/app/project/search-project/search-project.component.html delete mode 100644 src/clarity-seed/src/app/project/search-project/search-project.component.ts create mode 100644 src/clarity-seed/src/app/shared/filter/filter.component.css create mode 100644 src/clarity-seed/src/app/shared/filter/filter.component.html create mode 100644 src/clarity-seed/src/app/shared/filter/filter.component.ts create mode 100644 src/clarity-seed/src/app/shared/harbor-action-overflow/harbor-action-overflow.html create mode 100644 src/clarity-seed/src/app/shared/harbor-action-overflow/harbor-action-overflow.ts create mode 100644 src/clarity-seed/src/app/user/new-user-form.component.html create mode 100644 src/clarity-seed/src/app/user/new-user-form.component.ts create mode 100644 src/clarity-seed/src/app/user/new-user-modal.component.html create mode 100644 src/clarity-seed/src/app/user/new-user-modal.component.ts create mode 100644 src/clarity-seed/src/app/user/user.component.css create mode 100644 src/clarity-seed/src/app/user/user.service.ts create mode 100644 src/clarity-seed/src/app/user/user.ts diff --git a/src/clarity-seed/src/app/account/account-settings/account-settings-modal.component.html b/src/clarity-seed/src/app/account/account-settings/account-settings-modal.component.html index 6c54c0285..1fb92e62e 100644 --- a/src/clarity-seed/src/app/account/account-settings/account-settings-modal.component.html +++ b/src/clarity-seed/src/app/account/account-settings/account-settings-modal.component.html @@ -1,6 +1,6 @@ - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/clarity-seed/src/app/base/harbor-shell/harbor-shell.component.ts b/src/clarity-seed/src/app/base/harbor-shell/harbor-shell.component.ts index 8ccf6c6b2..926c7ac73 100644 --- a/src/clarity-seed/src/app/base/harbor-shell/harbor-shell.component.ts +++ b/src/clarity-seed/src/app/base/harbor-shell/harbor-shell.component.ts @@ -77,11 +77,4 @@ export class HarborShellComponent implements OnInit { this.isSearchResultsOpened = false; } } - - //Watch password whether changed - watchPwdChange(event: any): void { - if (event) { - this.navigator.logOut(true); - } - } } \ No newline at end of file diff --git a/src/clarity-seed/src/app/base/navigator/navigator.component.html b/src/clarity-seed/src/app/base/navigator/navigator.component.html index ecd7688e8..652175c3e 100644 --- a/src/clarity-seed/src/app/base/navigator/navigator.component.html +++ b/src/clarity-seed/src/app/base/navigator/navigator.component.html @@ -12,19 +12,6 @@ - - - - diff --git a/src/clarity-seed/src/app/base/navigator/navigator.component.ts b/src/clarity-seed/src/app/base/navigator/navigator.component.ts index 72661a469..95e05b6c4 100644 --- a/src/clarity-seed/src/app/base/navigator/navigator.component.ts +++ b/src/clarity-seed/src/app/base/navigator/navigator.component.ts @@ -32,6 +32,10 @@ export class NavigatorComponent implements OnInit { return this.sessionUser != null; } + public get accountName(): string { + return this.sessionUser?this.sessionUser.username: ""; + } + //Open the account setting dialog openAccountSettingsModal(): void { this.showAccountSettingsModal.emit({ @@ -54,17 +58,12 @@ export class NavigatorComponent implements OnInit { } //Log out system - logOut(reSignIn: boolean): void { + logOut(): void { this.session.signOff() .then(() => { this.sessionUser = null; - if (reSignIn) { - //Naviagte to the sign in route - this.router.navigate(["/sign-in"]); - } else { - //Naviagte to the default route - this.router.navigate(["/harbor"]); - } + //Naviagte to the sign in route + this.router.navigate(["/sign-in"]); }) .catch()//TODO: } diff --git a/src/clarity-seed/src/app/log/audit-log.component.html b/src/clarity-seed/src/app/log/audit-log.component.html index f8cc555d2..1be59aeb2 100644 --- a/src/clarity-seed/src/app/log/audit-log.component.html +++ b/src/clarity-seed/src/app/log/audit-log.component.html @@ -1,8 +1,28 @@
-
-
- +
+
+ +
+
+ +
+
+
+
+ + + + +
+
+ +
@@ -13,12 +33,12 @@ Timestamp {{l.username}} - {{l.repoName}} - {{l.tag}} + {{l.repo_name}} + {{l.repo_tag}} {{l.operation}} - {{l.timestamp}} + {{l.op_time}} - {{auditLogs.length}} item(s) + {{ (auditLogs ? auditLogs.length : 0) }} item(s)
\ No newline at end of file diff --git a/src/clarity-seed/src/app/log/audit-log.component.ts b/src/clarity-seed/src/app/log/audit-log.component.ts index bd9468880..375a3007c 100644 --- a/src/clarity-seed/src/app/log/audit-log.component.ts +++ b/src/clarity-seed/src/app/log/audit-log.component.ts @@ -1,18 +1,138 @@ import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute, Params, Router } from '@angular/router'; + import { AuditLog } from './audit-log'; +import { SessionUser } from '../shared/session-user'; + +import { AuditLogService } from './audit-log.service'; +import { SessionService } from '../shared/session.service'; +import { MessageService } from '../global-message/message.service'; + +export const optionalSearch: {} = {0: 'Advanced', 1: 'Simple'}; + + +export class FilterOption { + key: string; + description: string; + checked: boolean; + + constructor(private iKey: string, private iDescription: string, private iChecked: boolean) { + this.key = iKey; + this.description = iDescription; + this.checked = iChecked; + } + + toString(): string { + return 'key:' + this.key + ', description:' + this.description + ', checked:' + this.checked + '\n'; + } +} @Component({ - templateUrl: './audit-log.component.html' + selector: 'audit-log', + templateUrl: './audit-log.component.html', + styleUrls: [ 'audit-log.css' ] }) export class AuditLogComponent implements OnInit { + currentUser: SessionUser; + projectId: number; + queryParam: AuditLog = new AuditLog(); auditLogs: AuditLog[]; + + toggleName = optionalSearch; + currentOption: number = 0; + filterOptions: FilterOption[] = [ + new FilterOption('all', 'All Operations', true), + new FilterOption('pull', 'Pull', true), + new FilterOption('push', 'Push', true), + new FilterOption('create', 'Create', true), + new FilterOption('delete', 'Delete', true), + new FilterOption('others', 'Others', true) + ]; + + constructor(private route: ActivatedRoute, private router: Router, private auditLogService: AuditLogService, private messageService: MessageService) { + //Get current user from registered resolver. + this.route.data.subscribe(data=>this.currentUser = data['auditLogResolver']); + } ngOnInit(): void { - this.auditLogs = [ - { username: 'Admin', repoName: 'project01', tag: '', operation: 'create', timestamp: '2016-12-23 12:05:17' }, - { username: 'Admin', repoName: 'project01/ubuntu', tag: '14.04', operation: 'push', timestamp: '2016-12-30 14:52:23' }, - { username: 'user1', repoName: 'project01/mysql', tag: '5.6', operation: 'pull', timestamp: '2016-12-30 12:12:33' } - ]; + this.projectId = +this.route.snapshot.parent.params['id']; + console.log('Get projectId from route params snapshot:' + this.projectId); + this.queryParam.project_id = this.projectId; + this.retrieve(this.queryParam); + } + + retrieve(queryParam: AuditLog): void { + this.auditLogService + .listAuditLogs(queryParam) + .subscribe( + response=>this.auditLogs = response, + error=>{ + this.router.navigate(['/harbor', 'projects']); + this.messageService.announceMessage('Failed to list audit logs with project ID:' + queryParam.project_id); + } + ); + } + + doSearchAuditLogs(searchUsername: string): void { + this.queryParam.username = searchUsername; + this.retrieve(this.queryParam); + } + + doSearchByTimeRange(strDate: string, target: string): void { + let oneDayOffset = 3600 * 24; + switch(target) { + case 'begin': + this.queryParam.begin_timestamp = new Date(strDate).getTime() / 1000; + break; + case 'end': + this.queryParam.end_timestamp = new Date(strDate).getTime() / 1000 + oneDayOffset; + break; + } + console.log('Search audit log filtered by time range, begin: ' + this.queryParam.begin_timestamp + ', end:' + this.queryParam.end_timestamp); + this.retrieve(this.queryParam); + } + + doSearchByOptions() { + let selectAll = true; + let operationFilter: string[] = []; + for(var i in this.filterOptions) { + let filterOption = this.filterOptions[i]; + if(filterOption.checked) { + operationFilter.push(this.filterOptions[i].key); + }else{ + selectAll = false; + } + } + if(selectAll) { + operationFilter = []; + } + this.queryParam.keywords = operationFilter.join('/'); + this.retrieve(this.queryParam); + console.log('Search option filter:' + operationFilter.join('/')); + } + + toggleOptionalName(option: number): void { + (option === 1) ? this.currentOption = 0 : this.currentOption = 1; + } + + toggleFilterOption(option: string): void { + let selectedOption = this.filterOptions.find(value =>(value.key === option)); + selectedOption.checked = !selectedOption.checked; + if(selectedOption.key === 'all') { + this.filterOptions.filter(value=> value.key !== selectedOption.key).forEach(value => value.checked = selectedOption.checked); + } else { + if(!selectedOption.checked) { + this.filterOptions.find(value=>value.key === 'all').checked = false; + } + let selectAll = true; + this.filterOptions.filter(value=> value.key !== 'all').forEach(value =>{ + if(!value.checked) { + selectAll = false; + } + }); + this.filterOptions.find(value=>value.key === 'all').checked = selectAll; + } + this.doSearchByOptions(); } } \ No newline at end of file diff --git a/src/clarity-seed/src/app/log/audit-log.css b/src/clarity-seed/src/app/log/audit-log.css new file mode 100644 index 000000000..32fc27c22 --- /dev/null +++ b/src/clarity-seed/src/app/log/audit-log.css @@ -0,0 +1,3 @@ +.advance-option { + font-size: 12px; +} diff --git a/src/clarity-seed/src/app/log/audit-log.service.ts b/src/clarity-seed/src/app/log/audit-log.service.ts new file mode 100644 index 000000000..ce0ac3e7a --- /dev/null +++ b/src/clarity-seed/src/app/log/audit-log.service.ts @@ -0,0 +1,35 @@ +import { Injectable } from '@angular/core'; +import { Http, Headers, RequestOptions } from '@angular/http'; + +import { BaseService } from '../service/base.service'; + +import { AuditLog } from './audit-log'; + +import { Observable } from 'rxjs/Observable'; +import 'rxjs/add/operator/catch'; +import 'rxjs/add/operator/map'; +import 'rxjs/add/observable/throw'; + +export const urlPrefix = ''; + +@Injectable() +export class AuditLogService extends BaseService { + + constructor(private http: Http) { + super(); + } + + listAuditLogs(queryParam: AuditLog): Observable { + return this.http + .post(urlPrefix + `/api/projects/${queryParam.project_id}/logs/filter`, { + begin_timestamp: queryParam.begin_timestamp, + end_timestamp: queryParam.end_timestamp, + keywords: queryParam.keywords, + operation: queryParam.operation, + project_id: queryParam.project_id, + username: queryParam.username }) + .map(response=>response.json() as AuditLog[]) + .catch(error=>this.handleError(error)); + } + +} \ No newline at end of file diff --git a/src/clarity-seed/src/app/log/audit-log.ts b/src/clarity-seed/src/app/log/audit-log.ts index 23f2963b2..d008a9ef6 100644 --- a/src/clarity-seed/src/app/log/audit-log.ts +++ b/src/clarity-seed/src/app/log/audit-log.ts @@ -1,7 +1,30 @@ +/* + { + "log_id": 3, + "user_id": 0, + "project_id": 0, + "repo_name": "library/mysql", + "repo_tag": "5.6", + "guid": "", + "operation": "push", + "op_time": "2017-02-14T09:22:58Z", + "username": "admin", + "keywords": "", + "BeginTime": "0001-01-01T00:00:00Z", + "begin_timestamp": 0, + "EndTime": "0001-01-01T00:00:00Z", + "end_timestamp": 0 + } +*/ export class AuditLog { + log_id: number; + project_id: number; username: string; - repoName: string; - tag: string; + repo_name: string; + repo_tag: string; operation: string; - timestamp: string; + op_time: Date; + begin_timestamp: number = 0; + end_timestamp: number = 0; + keywords: string; } \ No newline at end of file diff --git a/src/clarity-seed/src/app/log/log.module.ts b/src/clarity-seed/src/app/log/log.module.ts index f92accfa3..307df9dea 100644 --- a/src/clarity-seed/src/app/log/log.module.ts +++ b/src/clarity-seed/src/app/log/log.module.ts @@ -1,10 +1,11 @@ import { NgModule } from '@angular/core'; import { AuditLogComponent } from './audit-log.component'; import { SharedModule } from '../shared/shared.module'; - +import { AuditLogService } from './audit-log.service'; @NgModule({ imports: [ SharedModule ], declarations: [ AuditLogComponent ], + providers: [ AuditLogService ], exports: [ AuditLogComponent ] }) export class LogModule {} \ No newline at end of file diff --git a/src/clarity-seed/src/app/project/create-project/create-project.component.ts b/src/clarity-seed/src/app/project/create-project/create-project.component.ts index 3f66ca179..a72c2e178 100644 --- a/src/clarity-seed/src/app/project/create-project/create-project.component.ts +++ b/src/clarity-seed/src/app/project/create-project/create-project.component.ts @@ -37,9 +37,11 @@ export class CreateProjectComponent { if (error instanceof Response) { switch(error.status) { case 409: - this.errorMessage = 'Project name already exists.'; break; + this.errorMessage = 'Project name already exists.'; + break; case 400: - this.errorMessage = 'Project name is illegal.'; break; + this.errorMessage = 'Project name is illegal.'; + break; default: this.errorMessage = 'Unknown error for project name.'; this.messageService.announceMessage(this.errorMessage); diff --git a/src/clarity-seed/src/app/project/filter-project/filter-project.component.html b/src/clarity-seed/src/app/project/filter-project/filter-project.component.html deleted file mode 100644 index 44d600707..000000000 --- a/src/clarity-seed/src/app/project/filter-project/filter-project.component.html +++ /dev/null @@ -1,9 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/clarity-seed/src/app/project/filter-project/filter-project.component.ts b/src/clarity-seed/src/app/project/filter-project/filter-project.component.ts deleted file mode 100644 index 3db3fa14a..000000000 --- a/src/clarity-seed/src/app/project/filter-project/filter-project.component.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Component, Output, EventEmitter } from '@angular/core'; - -export const projectTypes = [ - { 'key' : 0, 'value': 'My Projects' }, - { 'key' : 1, 'value': 'Public Projects'} -]; - -@Component({ - selector: 'filter-project', - templateUrl: 'filter-project.component.html' -}) -export class FilterProjectComponent { - - @Output() filter = new EventEmitter(); - types = projectTypes; - currentType = projectTypes[0]; - - doFilter(type: number) { - console.log('Filtered projects by:' + type); - this.currentType = projectTypes.find(item=>item.key === type); - this.filter.emit(type); - } -} \ No newline at end of file diff --git a/src/clarity-seed/src/app/project/list-project/list-project.component.html b/src/clarity-seed/src/app/project/list-project/list-project.component.html index 6ecd22a43..004b96696 100644 --- a/src/clarity-seed/src/app/project/list-project/list-project.component.html +++ b/src/clarity-seed/src/app/project/list-project/list-project.component.html @@ -1,10 +1,10 @@ - + Name Public/Private Repositories Creation time Description - +