Merge pull request #10223 from AllForNothing/master

Add links to view doc for scanners ui(cherry-pick #10220)
This commit is contained in:
Will Sun 2019-12-12 14:01:01 +08:00 committed by GitHub
commit 4cee3c7332
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 130 additions and 12 deletions

View File

@ -1,4 +1,17 @@
<clr-main-container> <clr-main-container>
<div class="clr-row scanner-info" *ngIf="showScannerInfo && isSystemAdmin ">
<div class="clr-col-2"></div>
<div class="clr-col text-center">
<clr-icon shape="info-standard" size="20"></clr-icon>
<span class="ml-05">{{'SCANNER.HELP_INFO_1' | translate }}
<a target="_blank" href="{{scannerDocUrl}}">{{'SCANNER.HELP_INFO_2' | translate }}</a>
</span>
</div>
<div class="clr-col-2 right">
<a class="all-scanners" href="#" routerLink="/harbor/interrogation-services/scanners">{{'SCANNER.ALL_SCANNERS' | translate }}</a>
<clr-icon (click)="closeInfo()" class="close-icon" shape="times" size="24"></clr-icon>
</div>
</div>
<global-message [isAppLevel]="true"></global-message> <global-message [isAppLevel]="true"></global-message>
<navigator (showAccountSettingsModal)="openModal($event)" (showDialogModalAction)="openModal($event)"></navigator> <navigator (showAccountSettingsModal)="openModal($event)" (showDialogModalAction)="openModal($event)"></navigator>
<div class="content-container"> <div class="content-container">

View File

@ -50,3 +50,32 @@ clr-vertical-nav {
} }
} }
.scanner-info {
margin-right: 0;
margin-left: 0;
background-color: #0079b8;
height: 2rem;
color: #fff;
align-items: center;
font-size: 0.5rem;
a {
cursor: pointer;
text-decoration: #bababa underline;
font-weight: 600;
}
a:hover, a:visited, a:link {
color: #fff;
}
}
.all-scanners {
margin-right: 1.5rem;
}
.close-icon {
margin-right: 1rem;
}
.ml-05 {
margin-left: 0.5rem;
}
.right {
text-align: right;
}

View File

@ -9,6 +9,7 @@ import { SearchTriggerService } from '../global-search/search-trigger.service';
import { HarborShellComponent } from './harbor-shell.component'; import { HarborShellComponent } from './harbor-shell.component';
import { ClarityModule } from "@clr/angular"; import { ClarityModule } from "@clr/angular";
import { of } from 'rxjs'; import { of } from 'rxjs';
import { ConfigScannerService } from "../../config/scanner/config-scanner.service";
describe('HarborShellComponent', () => { describe('HarborShellComponent', () => {
let component: HarborShellComponent; let component: HarborShellComponent;
@ -44,7 +45,11 @@ describe('HarborShellComponent', () => {
}; };
} }
}; };
let fakeConfigScannerService = {
getScanners() {
return of(true);
}
};
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [ imports: [
@ -58,7 +63,8 @@ describe('HarborShellComponent', () => {
TranslateService, TranslateService,
{ provide: SessionService, useValue: fakeSessionService }, { provide: SessionService, useValue: fakeSessionService },
{ provide: SearchTriggerService, useValue: fakeSearchTriggerService }, { provide: SearchTriggerService, useValue: fakeSearchTriggerService },
{ provide: AppConfigService, useValue: fakeAppConfigService } { provide: AppConfigService, useValue: fakeAppConfigService },
{ provide: ConfigScannerService, useValue: fakeConfigScannerService }
], ],
schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA] schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA]
}).compileComponents(); }).compileComponents();
@ -67,6 +73,7 @@ describe('HarborShellComponent', () => {
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(HarborShellComponent); fixture = TestBed.createComponent(HarborShellComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
component.showScannerInfo = true;
fixture.detectChanges(); fixture.detectChanges();
}); });

View File

@ -26,6 +26,10 @@ import { SessionService } from '../../shared/session.service';
import { AboutDialogComponent } from '../../shared/about-dialog/about-dialog.component'; import { AboutDialogComponent } from '../../shared/about-dialog/about-dialog.component';
import { SearchTriggerService } from '../global-search/search-trigger.service'; import { SearchTriggerService } from '../global-search/search-trigger.service';
import { CommonRoutes } from "../../../lib/entities/shared.const"; import { CommonRoutes } from "../../../lib/entities/shared.const";
import { ConfigScannerService, SCANNERS_DOC } from "../../config/scanner/config-scanner.service";
const HAS_SHOWED_SCANNER_INFO: string = 'hasShowScannerInfo';
const YES: string = 'yes';
@Component({ @Component({
selector: 'harbor-shell', selector: 'harbor-shell',
@ -56,13 +60,16 @@ export class HarborShellComponent implements OnInit, OnDestroy {
isLdapMode: boolean; isLdapMode: boolean;
isOidcMode: boolean; isOidcMode: boolean;
isHttpAuthMode: boolean; isHttpAuthMode: boolean;
showScannerInfo: boolean = false;
scannerDocUrl: string = SCANNERS_DOC;
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,
private router: Router, private router: Router,
private session: SessionService, private session: SessionService,
private searchTrigger: SearchTriggerService, private searchTrigger: SearchTriggerService,
private appConfigService: AppConfigService) { } private appConfigService: AppConfigService,
private scannerService: ConfigScannerService) { }
ngOnInit() { ngOnInit() {
if (this.appConfigService.isLdapMode()) { if (this.appConfigService.isLdapMode()) {
@ -81,8 +88,25 @@ export class HarborShellComponent implements OnInit, OnDestroy {
this.searchCloseSub = this.searchTrigger.searchCloseChan$.subscribe(close => { this.searchCloseSub = this.searchTrigger.searchCloseChan$.subscribe(close => {
this.isSearchResultsOpened = false; this.isSearchResultsOpened = false;
}); });
if (!(localStorage && localStorage.getItem(HAS_SHOWED_SCANNER_INFO) === YES)) {
this.getDefaultScanner();
}
}
closeInfo() {
if (localStorage) {
localStorage.setItem(HAS_SHOWED_SCANNER_INFO, YES);
}
this.showScannerInfo = false;
} }
getDefaultScanner() {
this.scannerService.getScanners()
.subscribe(scanners => {
if (scanners && scanners.length) {
this.showScannerInfo = scanners.some(scanner => scanner.is_default);
}
});
}
ngOnDestroy(): void { ngOnDestroy(): void {
if (this.searchSub) { if (this.searchSub) {
this.searchSub.unsubscribe(); this.searchSub.unsubscribe();

View File

@ -1,5 +1,13 @@
<div class="row"> <div class="row">
<div> <div>
<h4 class="mt-1">{{'SCANNER.IMAGE_SCANNERS' | translate }}
<clr-signpost>
<clr-signpost-content *clrIfOpen>
<a class="doc" target="_blank"
href="{{scannerDocUrl}}">{{'SCANNER.VIEW_DOC' | translate }}</a>
</clr-signpost-content>
</clr-signpost>
</h4>
<clr-datagrid [clrDgLoading]="onGoing" [(clrDgSingleSelected)]="selectedRow"> <clr-datagrid [clrDgLoading]="onGoing" [(clrDgSingleSelected)]="selectedRow">
<clr-dg-action-bar> <clr-dg-action-bar>
<div class="clr-row"> <div class="clr-row">

View File

@ -31,3 +31,6 @@
.margin-left-10 { .margin-left-10 {
margin-left: 10px; margin-left: 10px;
} }
.doc {
font-size: 0.7rem;
}

View File

@ -1,7 +1,7 @@
import { Component, ViewChild, OnInit, OnDestroy } from "@angular/core"; import { Component, ViewChild, OnInit, OnDestroy } from "@angular/core";
import { Scanner } from "./scanner"; import { Scanner } from "./scanner";
import { NewScannerModalComponent } from "./new-scanner-modal/new-scanner-modal.component"; import { NewScannerModalComponent } from "./new-scanner-modal/new-scanner-modal.component";
import { ConfigScannerService } from "./config-scanner.service"; import { ConfigScannerService, SCANNERS_DOC } from "./config-scanner.service";
import { finalize } from "rxjs/operators"; import { finalize } from "rxjs/operators";
import { MessageHandlerService } from "../../shared/message-handler/message-handler.service"; import { MessageHandlerService } from "../../shared/message-handler/message-handler.service";
import { ConfirmationButtons, ConfirmationState, ConfirmationTargets } from "../../shared/shared.const"; import { ConfirmationButtons, ConfirmationState, ConfirmationTargets } from "../../shared/shared.const";
@ -22,6 +22,7 @@ export class ConfigurationScannerComponent implements OnInit, OnDestroy {
@ViewChild(NewScannerModalComponent, {static: false}) @ViewChild(NewScannerModalComponent, {static: false})
newScannerDialog: NewScannerModalComponent; newScannerDialog: NewScannerModalComponent;
deletionSubscription: any; deletionSubscription: any;
scannerDocUrl: string = SCANNERS_DOC;
constructor( constructor(
private configScannerService: ConfigScannerService, private configScannerService: ConfigScannerService,
private errorHandler: ErrorHandler, private errorHandler: ErrorHandler,

View File

@ -5,6 +5,8 @@ import { catchError, map } from "rxjs/operators";
import { HttpClient } from "@angular/common/http"; import { HttpClient } from "@angular/common/http";
import { ScannerMetadata } from "./scanner-metadata"; import { ScannerMetadata } from "./scanner-metadata";
export const SCANNERS_DOC: string = "https://github.com/goharbor/harbor/blob/master/docs/harbor_compatibility_list.md";
@Injectable() @Injectable()
export class ConfigScannerService { export class ConfigScannerService {

View File

@ -1346,6 +1346,12 @@
"CONFIRM_DELETION": "Confirm Scanner deletion", "CONFIRM_DELETION": "Confirm Scanner deletion",
"NO_PROJECT_SCANNER": "No Scanner", "NO_PROJECT_SCANNER": "No Scanner",
"SET_UNHEALTHY_SCANNER": "Selected scanner:{{name}} is unhealthy", "SET_UNHEALTHY_SCANNER": "Selected scanner:{{name}} is unhealthy",
"SCANNED_BY": "Scanned by:" "SCANNED_BY": "Scanned by:",
"IMAGE_SCANNERS": "Image Scanners",
"VIEW_DOC": "view documentation",
"ALL_SCANNERS": "All scanners",
"HELP_INFO_1": "The default scanner has been installed. To install other scanners refer to the ",
"HELP_INFO_2": "documentation."
} }
} }

View File

@ -1343,6 +1343,11 @@
"CONFIRM_DELETION": "Confirm Scanner deletion", "CONFIRM_DELETION": "Confirm Scanner deletion",
"NO_PROJECT_SCANNER": "No Scanner", "NO_PROJECT_SCANNER": "No Scanner",
"SET_UNHEALTHY_SCANNER": "Selected scanner:{{name}} is unhealthy", "SET_UNHEALTHY_SCANNER": "Selected scanner:{{name}} is unhealthy",
"SCANNED_BY": "Scanned by:" "SCANNED_BY": "Scanned by:",
"IMAGE_SCANNERS": "Image Scanners",
"VIEW_DOC": "view documentation",
"ALL_SCANNERS": "All scanners",
"HELP_INFO_1": "The default scanner has been installed. To install other scanners refer to the ",
"HELP_INFO_2": "documentation."
} }
} }

View File

@ -1315,6 +1315,11 @@
"CONFIRM_DELETION": "Confirm Scanner deletion", "CONFIRM_DELETION": "Confirm Scanner deletion",
"NO_PROJECT_SCANNER": "No Scanner", "NO_PROJECT_SCANNER": "No Scanner",
"SET_UNHEALTHY_SCANNER": "Selected scanner:{{name}} is unhealthy", "SET_UNHEALTHY_SCANNER": "Selected scanner:{{name}} is unhealthy",
"SCANNED_BY": "Scanned by:" "SCANNED_BY": "Scanned by:",
"IMAGE_SCANNERS": "Image Scanners",
"VIEW_DOC": "view documentation",
"ALL_SCANNERS": "All scanners",
"HELP_INFO_1": "The default scanner has been installed. To install other scanners refer to the ",
"HELP_INFO_2": "documentation."
} }
} }

View File

@ -1340,7 +1340,12 @@
"CONFIRM_DELETION": "Confirm Scanner deletion", "CONFIRM_DELETION": "Confirm Scanner deletion",
"NO_PROJECT_SCANNER": "No Scanner", "NO_PROJECT_SCANNER": "No Scanner",
"SET_UNHEALTHY_SCANNER": "Selected scanner:{{name}} is unhealthy", "SET_UNHEALTHY_SCANNER": "Selected scanner:{{name}} is unhealthy",
"SCANNED_BY": "Scanned by:" "SCANNED_BY": "Scanned by:",
"IMAGE_SCANNERS": "Image Scanners",
"VIEW_DOC": "view documentation",
"ALL_SCANNERS": "All scanners",
"HELP_INFO_1": "The default scanner has been installed. To install other scanners refer to the ",
"HELP_INFO_2": "documentation."
} }
} }

View File

@ -1345,6 +1345,11 @@
"CONFIRM_DELETION": "Confirm Scanner deletion", "CONFIRM_DELETION": "Confirm Scanner deletion",
"NO_PROJECT_SCANNER": "No Scanner", "NO_PROJECT_SCANNER": "No Scanner",
"SET_UNHEALTHY_SCANNER": "Selected scanner:{{name}} is unhealthy", "SET_UNHEALTHY_SCANNER": "Selected scanner:{{name}} is unhealthy",
"SCANNED_BY": "Scanned by:" "SCANNED_BY": "Scanned by:",
"IMAGE_SCANNERS": "Image Scanners",
"VIEW_DOC": "view documentation",
"ALL_SCANNERS": "All scanners",
"HELP_INFO_1": "The default scanner has been installed. To install other scanners refer to the ",
"HELP_INFO_2": "documentation."
} }
} }

View File

@ -1342,6 +1342,11 @@
"CONFIRM_DELETION": "删除扫描器确认", "CONFIRM_DELETION": "删除扫描器确认",
"NO_PROJECT_SCANNER": "无扫描器", "NO_PROJECT_SCANNER": "无扫描器",
"SET_UNHEALTHY_SCANNER": "选择的扫描器:{{name}}是不健康的", "SET_UNHEALTHY_SCANNER": "选择的扫描器:{{name}}是不健康的",
"SCANNED_BY": "扫描器:" "SCANNED_BY": "扫描器:",
"IMAGE_SCANNERS": "镜像扫描器",
"VIEW_DOC": "查看文档",
"ALL_SCANNERS": "全部扫描器",
"HELP_INFO_1": "默认扫描器已安装。获取扫描器安装帮助,请查看",
"HELP_INFO_2": "文档。"
} }
} }

View File

@ -21,7 +21,7 @@
</clr-control-helper> </clr-control-helper>
</clr-checkbox-container> </clr-checkbox-container>
<clr-checkbox-container id="prevent-vulenrability-image" class="margin-top-05"> <clr-checkbox-container id="prevent-vulenrability-image" class="margin-top-05">
<label></label> <label><span *ngIf="!withNotary">{{ 'PROJECT_CONFIG.SECURITY' | translate }}</span></label>
<clr-checkbox-wrapper> <clr-checkbox-wrapper>
<input type="checkbox" clrCheckbox [(ngModel)]="projectPolicy.PreventVulImg" <input type="checkbox" clrCheckbox [(ngModel)]="projectPolicy.PreventVulImg"
name="prevent-vulenrability-image-input" [disabled]="!hasChangeConfigRole" /> name="prevent-vulenrability-image-input" [disabled]="!hasChangeConfigRole" />