mirror of
https://github.com/goharbor/harbor
synced 2025-04-22 14:50:02 +00:00
Merge pull request #2451 from steven-zou/master
Enable server-driven pagination for recent logs
This commit is contained in:
commit
36bb7cc2e0
@ -18,20 +18,20 @@
|
|||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/animations": "^4.0.1",
|
"@angular/animations": "^4.1.0",
|
||||||
"@angular/common": "^4.0.1",
|
"@angular/common": "^4.1.0",
|
||||||
"@angular/compiler": "^4.0.1",
|
"@angular/compiler": "^4.1.0",
|
||||||
"@angular/core": "^4.0.1",
|
"@angular/core": "^4.1.0",
|
||||||
"@angular/forms": "^4.0.1",
|
"@angular/forms": "^4.1.0",
|
||||||
"@angular/http": "^4.0.1",
|
"@angular/http": "^4.1.0",
|
||||||
"@angular/platform-browser": "^4.0.1",
|
"@angular/platform-browser": "^4.1.0",
|
||||||
"@angular/platform-browser-dynamic": "^4.0.1",
|
"@angular/platform-browser-dynamic": "^4.1.0",
|
||||||
"@angular/router": "^4.0.1",
|
"@angular/router": "^4.1.0",
|
||||||
"@webcomponents/custom-elements": "1.0.0-alpha.3",
|
"@webcomponents/custom-elements": "1.0.0-alpha.3",
|
||||||
"web-animations-js": "^2.2.1",
|
"web-animations-js": "^2.2.1",
|
||||||
"clarity-angular": "^0.9.0",
|
"clarity-angular": "^0.9.7",
|
||||||
"clarity-icons": "^0.9.0",
|
"clarity-icons": "^0.9.7",
|
||||||
"clarity-ui": "^0.9.0",
|
"clarity-ui": "^0.9.7",
|
||||||
"core-js": "^2.4.1",
|
"core-js": "^2.4.1",
|
||||||
"rxjs": "^5.0.1",
|
"rxjs": "^5.0.1",
|
||||||
"ts-helpers": "^1.1.1",
|
"ts-helpers": "^1.1.1",
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "harbor-ui",
|
"name": "harbor-ui",
|
||||||
"version": "0.1.24",
|
"version": "0.1.42",
|
||||||
"description": "Harbor shared UI components based on Clarity and Angular4",
|
"description": "Harbor shared UI components based on Clarity and Angular4",
|
||||||
"author": "Harbor",
|
"author": "VMware",
|
||||||
"module": "index.js",
|
"module": "index.js",
|
||||||
"main": "bundles/harborui.umd.min.js",
|
"main": "bundles/harborui.umd.min.js",
|
||||||
"jsnext:main": "index.js",
|
"jsnext:main": "index.js",
|
||||||
|
@ -3,7 +3,7 @@ import { By } from '@angular/platform-browser';
|
|||||||
import { HttpModule } from '@angular/http';
|
import { HttpModule } from '@angular/http';
|
||||||
import { DebugElement } from '@angular/core';
|
import { DebugElement } from '@angular/core';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
import { AccessLog, RequestQueryParams } from '../service/index';
|
import { AccessLog, AccessLogItem, RequestQueryParams } from '../service/index';
|
||||||
|
|
||||||
import { RecentLogComponent } from './recent-log.component';
|
import { RecentLogComponent } from './recent-log.component';
|
||||||
import { AccessLogService, AccessLogDefaultService } from '../service/access-log.service';
|
import { AccessLogService, AccessLogDefaultService } from '../service/access-log.service';
|
||||||
@ -18,7 +18,7 @@ describe('RecentLogComponent (inline template)', () => {
|
|||||||
let serviceConfig: IServiceConfig;
|
let serviceConfig: IServiceConfig;
|
||||||
let logService: AccessLogService;
|
let logService: AccessLogService;
|
||||||
let spy: jasmine.Spy;
|
let spy: jasmine.Spy;
|
||||||
let mockData: AccessLog[] = [{
|
let mockItems: AccessLogItem[] = [{
|
||||||
log_id: 23,
|
log_id: 23,
|
||||||
user_id: 45,
|
user_id: 45,
|
||||||
project_id: 11,
|
project_id: 11,
|
||||||
@ -37,6 +37,12 @@ describe('RecentLogComponent (inline template)', () => {
|
|||||||
op_time: "2017-03-09T02:29:59Z",
|
op_time: "2017-03-09T02:29:59Z",
|
||||||
username: "admin"
|
username: "admin"
|
||||||
}];
|
}];
|
||||||
|
let mockData: AccessLog = {
|
||||||
|
metadata: {
|
||||||
|
xTotalCount: 2
|
||||||
|
},
|
||||||
|
data: mockItems
|
||||||
|
};
|
||||||
let testConfig: IServiceConfig = {
|
let testConfig: IServiceConfig = {
|
||||||
logBaseEndpoint: "/api/logs/testing"
|
logBaseEndpoint: "/api/logs/testing"
|
||||||
};
|
};
|
||||||
@ -102,7 +108,7 @@ describe('RecentLogComponent (inline template)', () => {
|
|||||||
component.doFilter('push');
|
component.doFilter('push');
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(component.recentLogs.length).toEqual(1);
|
expect(component.recentLogs.length).toEqual(1);
|
||||||
let log: AccessLog = component.recentLogs[0];
|
let log: AccessLogItem = component.recentLogs[0];
|
||||||
expect(log).toBeTruthy();
|
expect(log).toBeTruthy();
|
||||||
expect(log.username).toEqual('admin');
|
expect(log.username).toEqual('admin');
|
||||||
});
|
});
|
||||||
|
@ -15,14 +15,16 @@ import { Component, OnInit } from '@angular/core';
|
|||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import {
|
import {
|
||||||
AccessLogService,
|
AccessLogService,
|
||||||
AccessLog
|
AccessLog,
|
||||||
|
AccessLogItem,
|
||||||
|
RequestQueryParams
|
||||||
} from '../service/index';
|
} from '../service/index';
|
||||||
import { ErrorHandler } from '../error-handler/index';
|
import { ErrorHandler } from '../error-handler/index';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
import { toPromise, CustomComparator } from '../utils';
|
import { toPromise, CustomComparator } from '../utils';
|
||||||
import { LOG_TEMPLATE, LOG_STYLES } from './recent-log.template';
|
import { LOG_TEMPLATE, LOG_STYLES } from './recent-log.template';
|
||||||
|
|
||||||
import { Comparator } from 'clarity-angular';
|
import { Comparator, State } from 'clarity-angular';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'hbr-log',
|
selector: 'hbr-log',
|
||||||
@ -31,13 +33,13 @@ import { Comparator } from 'clarity-angular';
|
|||||||
})
|
})
|
||||||
|
|
||||||
export class RecentLogComponent implements OnInit {
|
export class RecentLogComponent implements OnInit {
|
||||||
recentLogs: AccessLog[];
|
recentLogs: AccessLogItem[] = [];
|
||||||
logsCache: AccessLog[];
|
logsCache: AccessLog;
|
||||||
onGoing: boolean = false;
|
loading: boolean = true;
|
||||||
lines: number = 10; //Support 10, 25 and 50
|
|
||||||
currentTerm: string;
|
currentTerm: string;
|
||||||
|
|
||||||
loading: boolean;
|
pageSize: number = 15;
|
||||||
|
currentPage: number = 0;
|
||||||
|
|
||||||
opTimeComparator: Comparator<AccessLog> = new CustomComparator<AccessLog>('op_time', 'date');
|
opTimeComparator: Comparator<AccessLog> = new CustomComparator<AccessLog>('op_time', 'date');
|
||||||
|
|
||||||
@ -46,67 +48,140 @@ export class RecentLogComponent implements OnInit {
|
|||||||
private errorHandler: ErrorHandler) { }
|
private errorHandler: ErrorHandler) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.retrieveLogs();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleOnchange($event: any) {
|
public get totalCount(): number {
|
||||||
this.currentTerm = '';
|
return this.logsCache && this.logsCache.metadata ? this.logsCache.metadata.xTotalCount : 0;
|
||||||
if ($event && $event.target && $event.target["value"]) {
|
|
||||||
this.lines = $event.target["value"];
|
|
||||||
if (this.lines < 10) {
|
|
||||||
this.lines = 10;
|
|
||||||
}
|
|
||||||
this.retrieveLogs();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public get logNumber(): number {
|
|
||||||
return this.recentLogs ? this.recentLogs.length : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public get inProgress(): boolean {
|
public get inProgress(): boolean {
|
||||||
return this.onGoing;
|
return this.loading;
|
||||||
}
|
}
|
||||||
|
|
||||||
public doFilter(terms: string): void {
|
public doFilter(terms: string): void {
|
||||||
if (terms.trim() === "") {
|
if (terms.trim() === "") {
|
||||||
this.recentLogs = this.logsCache.filter(log => log.username != "");
|
//Clear search results
|
||||||
|
this.recentLogs = this.logsCache.data.filter(log => log.username != "");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.currentTerm = terms;
|
this.currentTerm = terms;
|
||||||
this.recentLogs = this.logsCache.filter(log => this.isMatched(terms, log));
|
this.recentLogs = this.logsCache.data.filter(log => this.isMatched(terms, log));
|
||||||
}
|
}
|
||||||
|
|
||||||
public refresh(): void {
|
public refresh(): void {
|
||||||
this.retrieveLogs();
|
this.currentTerm = "";
|
||||||
|
this.currentPage = 0;
|
||||||
|
this.load({});
|
||||||
}
|
}
|
||||||
|
|
||||||
retrieveLogs(): void {
|
load(state: State) {
|
||||||
if (this.lines < 10) {
|
let pageNumber: number = this._calculatePage(state);
|
||||||
this.lines = 10;
|
if (pageNumber !== this.currentPage) {
|
||||||
}
|
//load data
|
||||||
|
let params: RequestQueryParams = new RequestQueryParams();
|
||||||
|
params.set("page", '' + pageNumber);
|
||||||
|
params.set("page_size", '' + this.pageSize);
|
||||||
|
|
||||||
this.onGoing = true;
|
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
toPromise<AccessLog[]>(this.logService.getRecentLogs(this.lines))
|
toPromise<AccessLog>(this.logService.getRecentLogs(params))
|
||||||
.then(response => {
|
.then(response => {
|
||||||
this.onGoing = false;
|
|
||||||
this.loading = false;
|
|
||||||
this.logsCache = response; //Keep the data
|
this.logsCache = response; //Keep the data
|
||||||
this.recentLogs = this.logsCache.filter(log => log.username != "");//To display
|
this.recentLogs = this.logsCache.data.filter(log => log.username != "");//To display
|
||||||
|
|
||||||
|
//Do customized filter
|
||||||
|
this._doFilter(state);
|
||||||
|
|
||||||
|
//Do customized sorting
|
||||||
|
this._doSorting(state);
|
||||||
|
|
||||||
|
this.currentPage = pageNumber;
|
||||||
|
|
||||||
|
this.loading = false;
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
this.onGoing = false;
|
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.errorHandler.error(error);
|
this.errorHandler.error(error);
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
this.recentLogs = this.logsCache.data.filter(log => log.username != "");//Reset data
|
||||||
|
|
||||||
|
//Do customized filter
|
||||||
|
this._doFilter(state);
|
||||||
|
|
||||||
|
//Do customized sorting
|
||||||
|
this._doSorting(state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isMatched(terms: string, log: AccessLog): boolean {
|
isMatched(terms: string, log: AccessLogItem): boolean {
|
||||||
let reg = new RegExp('.*' + terms + '.*', 'i');
|
let reg = new RegExp('.*' + terms + '.*', 'i');
|
||||||
return reg.test(log.username) ||
|
return reg.test(log.username) ||
|
||||||
reg.test(log.repo_name) ||
|
reg.test(log.repo_name) ||
|
||||||
reg.test(log.operation) ||
|
reg.test(log.operation) ||
|
||||||
reg.test(log.repo_tag);
|
reg.test(log.repo_tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_calculatePage(state: State): number {
|
||||||
|
if (!state || !state.page) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.ceil((state.page.to + 1) / state.page.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
_doFilter(state: State): void {
|
||||||
|
if (!this.recentLogs || this.recentLogs.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!state || !state.filters || state.filters.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.filters.forEach((filter: {
|
||||||
|
property: string;
|
||||||
|
value: string;
|
||||||
|
}) => {
|
||||||
|
this.recentLogs = this.recentLogs.filter(logItem => this._regexpFilter(filter["value"], logItem[filter["property"]]));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_regexpFilter(terms: string, testedValue: any): boolean {
|
||||||
|
let reg = new RegExp('.*' + terms + '.*', 'i');
|
||||||
|
return reg.test(testedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
_doSorting(state: State): void {
|
||||||
|
if (!this.recentLogs || this.recentLogs.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!state || !state.sort) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.recentLogs = this.recentLogs.sort((a: AccessLogItem, b: AccessLogItem) => {
|
||||||
|
let comp: number = 0;
|
||||||
|
if (typeof state.sort.by !== "string") {
|
||||||
|
comp = state.sort.by.compare(a, b);
|
||||||
|
} else {
|
||||||
|
let propA = a[state.sort.by.toString()], propB = b[state.sort.by.toString()];
|
||||||
|
if (typeof propA === "string") {
|
||||||
|
comp = propA.localeCompare(propB);
|
||||||
|
} else {
|
||||||
|
if (propA > propB) {
|
||||||
|
comp = 1;
|
||||||
|
} else if (propA < propB) {
|
||||||
|
comp = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.sort.reverse) {
|
||||||
|
comp = -comp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return comp;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
@ -8,36 +8,33 @@ export const LOG_TEMPLATE: string = `
|
|||||||
<div class="row flex-items-xs-between flex-items-xs-bottom">
|
<div class="row flex-items-xs-between flex-items-xs-bottom">
|
||||||
<div></div>
|
<div></div>
|
||||||
<div class="action-head-pos">
|
<div class="action-head-pos">
|
||||||
<div class="select log-select">
|
|
||||||
<select id="log_display_num" (change)="handleOnchange($event)">
|
|
||||||
<option value="10">{{'RECENT_LOG.SUB_TITLE' | translate}} 10 {{'RECENT_LOG.SUB_TITLE_SUFIX' | translate}}</option>
|
|
||||||
<option value="25">{{'RECENT_LOG.SUB_TITLE' | translate}} 25 {{'RECENT_LOG.SUB_TITLE_SUFIX' | translate}}</option>
|
|
||||||
<option value="50">{{'RECENT_LOG.SUB_TITLE' | translate}} 50 {{'RECENT_LOG.SUB_TITLE_SUFIX' | translate}}</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="item-divider"></div>
|
|
||||||
<hbr-filter filterPlaceholder='{{"AUDIT_LOG.FILTER_PLACEHOLDER" | translate}}' (filter)="doFilter($event)" [currentValue]="currentTerm"></hbr-filter>
|
<hbr-filter filterPlaceholder='{{"AUDIT_LOG.FILTER_PLACEHOLDER" | translate}}' (filter)="doFilter($event)" [currentValue]="currentTerm"></hbr-filter>
|
||||||
<span (click)="refresh()" class="refresh-btn">
|
<span (click)="refresh()" class="refresh-btn">
|
||||||
<clr-icon shape="refresh" [hidden]="inProgress" ng-disabled="inProgress"></clr-icon>
|
<clr-icon shape="refresh" [hidden]="inProgress" ng-disabled="inProgress"></clr-icon>
|
||||||
<span class="spinner spinner-inline" [hidden]="inProgress === false"></span>
|
<span class="spinner spinner-inline" [hidden]="!inProgress"></span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<clr-datagrid [clrDgLoading]="loading">
|
<clr-datagrid (clrDgRefresh)="load($event)" [clrDgLoading]="loading">
|
||||||
<clr-dg-column [clrDgField]="'username'">{{'AUDIT_LOG.USERNAME' | translate}}</clr-dg-column>
|
<clr-dg-column [clrDgField]="'username'">{{'AUDIT_LOG.USERNAME' | translate}}</clr-dg-column>
|
||||||
<clr-dg-column [clrDgField]="'repo_name'">{{'AUDIT_LOG.REPOSITORY_NAME' | translate}}</clr-dg-column>
|
<clr-dg-column [clrDgField]="'repo_name'">{{'AUDIT_LOG.REPOSITORY_NAME' | translate}}</clr-dg-column>
|
||||||
<clr-dg-column [clrDgField]="'repo_tag'">{{'AUDIT_LOG.TAGS' | translate}}</clr-dg-column>
|
<clr-dg-column [clrDgField]="'repo_tag'">{{'AUDIT_LOG.TAGS' | translate}}</clr-dg-column>
|
||||||
<clr-dg-column [clrDgField]="'operation'">{{'AUDIT_LOG.OPERATION' | translate}}</clr-dg-column>
|
<clr-dg-column [clrDgField]="'operation'">{{'AUDIT_LOG.OPERATION' | translate}}</clr-dg-column>
|
||||||
<clr-dg-column [clrDgSortBy]="opTimeComparator">{{'AUDIT_LOG.TIMESTAMP' | translate}}</clr-dg-column>
|
<clr-dg-column [clrDgSortBy]="opTimeComparator">{{'AUDIT_LOG.TIMESTAMP' | translate}}</clr-dg-column>
|
||||||
<clr-dg-row *clrDgItems="let l of recentLogs">
|
<clr-dg-placeholder>We couldn't find any logs!</clr-dg-placeholder>
|
||||||
|
<clr-dg-row *ngFor="let l of recentLogs">
|
||||||
<clr-dg-cell>{{l.username}}</clr-dg-cell>
|
<clr-dg-cell>{{l.username}}</clr-dg-cell>
|
||||||
<clr-dg-cell>{{l.repo_name}}</clr-dg-cell>
|
<clr-dg-cell>{{l.repo_name}}</clr-dg-cell>
|
||||||
<clr-dg-cell>{{l.repo_tag}}</clr-dg-cell>
|
<clr-dg-cell>{{l.repo_tag}}</clr-dg-cell>
|
||||||
<clr-dg-cell>{{l.operation}}</clr-dg-cell>
|
<clr-dg-cell>{{l.operation}}</clr-dg-cell>
|
||||||
<clr-dg-cell>{{l.op_time | date: 'short'}}</clr-dg-cell>
|
<clr-dg-cell>{{l.op_time | date: 'short'}}</clr-dg-cell>
|
||||||
</clr-dg-row>
|
</clr-dg-row>
|
||||||
<clr-dg-footer>{{ (recentLogs ? recentLogs.length : 0) }} {{'AUDIT_LOG.ITEMS' | translate}}</clr-dg-footer>
|
<clr-dg-footer>
|
||||||
|
{{pagination.firstItem + 1}} - {{pagination.lastItem + 1}}
|
||||||
|
of {{pagination.totalItems}} {{'AUDIT_LOG.ITEMS' | translate}}
|
||||||
|
<clr-dg-pagination #pagination [clrDgPageSize]="pageSize" [clrDgTotalItems]="totalCount"></clr-dg-pagination>
|
||||||
|
</clr-dg-footer>
|
||||||
</clr-datagrid>
|
</clr-datagrid>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
import { RequestQueryParams } from './RequestQueryParams';
|
import { RequestQueryParams } from './RequestQueryParams';
|
||||||
import { AccessLog } from './interface';
|
import { AccessLog, AccessLogItem } from './interface';
|
||||||
import { Injectable, Inject } from "@angular/core";
|
import { Injectable, Inject } from "@angular/core";
|
||||||
import 'rxjs/add/observable/of';
|
import 'rxjs/add/observable/of';
|
||||||
import { SERVICE_CONFIG, IServiceConfig } from '../service.config';
|
import { SERVICE_CONFIG, IServiceConfig } from '../service.config';
|
||||||
import { Http, URLSearchParams } from '@angular/http';
|
import { Http, URLSearchParams } from '@angular/http';
|
||||||
import { HTTP_JSON_OPTIONS } from '../utils';
|
import { HTTP_JSON_OPTIONS, buildHttpRequestOptions } from '../utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define service methods to handle the access log related things.
|
* Define service methods to handle the access log related things.
|
||||||
@ -34,12 +34,12 @@ export abstract class AccessLogService {
|
|||||||
* Get the recent logs.
|
* Get the recent logs.
|
||||||
*
|
*
|
||||||
* @abstract
|
* @abstract
|
||||||
* @param {number} lines : Specify how many lines should be returned.
|
* @param {RequestQueryParams} [queryParams]
|
||||||
* @returns {(Observable<AccessLog[]> | Promise<AccessLog[]> | AccessLog[])}
|
* @returns {(Observable<AccessLog> | Promise<AccessLog> | AccessLog)}
|
||||||
*
|
*
|
||||||
* @memberOf AccessLogService
|
* @memberOf AccessLogService
|
||||||
*/
|
*/
|
||||||
abstract getRecentLogs(lines: number): Observable<AccessLog[]> | Promise<AccessLog[]> | AccessLog[];
|
abstract getRecentLogs(queryParams?: RequestQueryParams): Observable<AccessLog> | Promise<AccessLog> | AccessLog;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -61,14 +61,34 @@ export class AccessLogDefaultService extends AccessLogService {
|
|||||||
return Observable.of([]);
|
return Observable.of([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getRecentLogs(lines: number): Observable<AccessLog[]> | Promise<AccessLog[]> | AccessLog[] {
|
public getRecentLogs(queryParams?: RequestQueryParams): Observable<AccessLog> | Promise<AccessLog> | AccessLog {
|
||||||
let url: string = this.config.logBaseEndpoint ? this.config.logBaseEndpoint : "";
|
let url: string = this.config.logBaseEndpoint ? this.config.logBaseEndpoint : "";
|
||||||
if (url === '') {
|
if (url === '') {
|
||||||
url = '/api/logs';
|
url = '/api/logs';
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.http.get(url+`?page_size=${lines}`, HTTP_JSON_OPTIONS).toPromise()
|
return this.http.get(url, queryParams ? buildHttpRequestOptions(queryParams) : HTTP_JSON_OPTIONS).toPromise()
|
||||||
.then(response => response.json() as AccessLog[])
|
.then(response => {
|
||||||
|
let result: AccessLog = {
|
||||||
|
metadata: {
|
||||||
|
xTotalCount: 0
|
||||||
|
},
|
||||||
|
data: []
|
||||||
|
};
|
||||||
|
let xHeader: string | null = "0";
|
||||||
|
if (response && response.headers) {
|
||||||
|
xHeader = response.headers.get("X-Total-Count");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result && result.metadata) {
|
||||||
|
result.metadata.xTotalCount = parseInt(xHeader ? xHeader : "0", 0);
|
||||||
|
if (result.metadata.xTotalCount > 0) {
|
||||||
|
result.data = response.json() as AccessLogItem[];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
})
|
||||||
.catch(error => Promise.reject(error));
|
.catch(error => Promise.reject(error));
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -95,6 +95,16 @@ export interface ReplicationJob extends Base {
|
|||||||
tags: string;
|
tags: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for storing metadata of response.
|
||||||
|
*
|
||||||
|
* @export
|
||||||
|
* @interface Metadata
|
||||||
|
*/
|
||||||
|
export interface Metadata {
|
||||||
|
xTotalCount: number;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for access log.
|
* Interface for access log.
|
||||||
*
|
*
|
||||||
@ -102,6 +112,18 @@ export interface ReplicationJob extends Base {
|
|||||||
* @interface AccessLog
|
* @interface AccessLog
|
||||||
*/
|
*/
|
||||||
export interface AccessLog {
|
export interface AccessLog {
|
||||||
|
metadata?: Metadata;
|
||||||
|
data: AccessLogItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The access log data.
|
||||||
|
*
|
||||||
|
* @export
|
||||||
|
* @interface AccessLogItem
|
||||||
|
*/
|
||||||
|
export interface AccessLogItem {
|
||||||
|
[key: string]: any
|
||||||
log_id: number;
|
log_id: number;
|
||||||
project_id: number;
|
project_id: number;
|
||||||
repo_name: string;
|
repo_name: string;
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
"stripInternal": true,
|
"stripInternal": true,
|
||||||
"emitDecoratorMetadata": true,
|
"emitDecoratorMetadata": true,
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
"strictNullChecks": true,
|
"strictNullChecks": false,
|
||||||
"noImplicitAny": true,
|
"noImplicitAny": true,
|
||||||
"module": "es2015",
|
"module": "es2015",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user