diff --git a/src/portal/src/app/base/harbor-shell/harbor-shell.component.html b/src/portal/src/app/base/harbor-shell/harbor-shell.component.html index bbc1bfb77..e156cb66d 100644 --- a/src/portal/src/app/base/harbor-shell/harbor-shell.component.html +++ b/src/portal/src/app/base/harbor-shell/harbor-shell.component.html @@ -1,5 +1,18 @@ - +
+
+
+ + {{'SCANNER.HELP_INFO_1' | translate }} + {{'SCANNER.HELP_INFO_2' | translate }} + +
+ +
+
{ let component: HarborShellComponent; @@ -44,7 +45,11 @@ describe('HarborShellComponent', () => { }; } }; - + let fakeConfigScannerService = { + getScanners() { + return of(true); + } + }; beforeEach(async(() => { TestBed.configureTestingModule({ imports: [ @@ -58,7 +63,8 @@ describe('HarborShellComponent', () => { TranslateService, { provide: SessionService, useValue: fakeSessionService }, { provide: SearchTriggerService, useValue: fakeSearchTriggerService }, - { provide: AppConfigService, useValue: fakeAppConfigService } + { provide: AppConfigService, useValue: fakeAppConfigService }, + { provide: ConfigScannerService, useValue: fakeConfigScannerService } ], schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA] }).compileComponents(); @@ -67,6 +73,7 @@ describe('HarborShellComponent', () => { beforeEach(() => { fixture = TestBed.createComponent(HarborShellComponent); component = fixture.componentInstance; + component.showScannerInfo = true; fixture.detectChanges(); }); diff --git a/src/portal/src/app/base/harbor-shell/harbor-shell.component.ts b/src/portal/src/app/base/harbor-shell/harbor-shell.component.ts index 0794fe11b..24a50908e 100644 --- a/src/portal/src/app/base/harbor-shell/harbor-shell.component.ts +++ b/src/portal/src/app/base/harbor-shell/harbor-shell.component.ts @@ -26,6 +26,10 @@ import { SessionService } from '../../shared/session.service'; import { AboutDialogComponent } from '../../shared/about-dialog/about-dialog.component'; import { SearchTriggerService } from '../global-search/search-trigger.service'; 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({ selector: 'harbor-shell', @@ -56,13 +60,16 @@ export class HarborShellComponent implements OnInit, OnDestroy { isLdapMode: boolean; isOidcMode: boolean; isHttpAuthMode: boolean; + showScannerInfo: boolean = false; + scannerDocUrl: string = SCANNERS_DOC; constructor( private route: ActivatedRoute, private router: Router, private session: SessionService, private searchTrigger: SearchTriggerService, - private appConfigService: AppConfigService) { } + private appConfigService: AppConfigService, + private scannerService: ConfigScannerService) { } ngOnInit() { if (this.appConfigService.isLdapMode()) { @@ -81,8 +88,25 @@ export class HarborShellComponent implements OnInit, OnDestroy { this.searchCloseSub = this.searchTrigger.searchCloseChan$.subscribe(close => { 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 { if (this.searchSub) { this.searchSub.unsubscribe(); diff --git a/src/portal/src/app/config/scanner/config-scanner.component.html b/src/portal/src/app/config/scanner/config-scanner.component.html index fbf434789..123f488b1 100644 --- a/src/portal/src/app/config/scanner/config-scanner.component.html +++ b/src/portal/src/app/config/scanner/config-scanner.component.html @@ -1,5 +1,13 @@
+

{{'SCANNER.IMAGE_SCANNERS' | translate }} + + + {{'SCANNER.VIEW_DOC' | translate }} + + +

diff --git a/src/portal/src/app/config/scanner/config-scanner.component.scss b/src/portal/src/app/config/scanner/config-scanner.component.scss index f6c8b3ff9..1e2e42d45 100644 --- a/src/portal/src/app/config/scanner/config-scanner.component.scss +++ b/src/portal/src/app/config/scanner/config-scanner.component.scss @@ -31,3 +31,6 @@ .margin-left-10 { margin-left: 10px; } +.doc { + font-size: 0.7rem; +} diff --git a/src/portal/src/app/config/scanner/config-scanner.component.ts b/src/portal/src/app/config/scanner/config-scanner.component.ts index c2010eb1e..fc840211e 100644 --- a/src/portal/src/app/config/scanner/config-scanner.component.ts +++ b/src/portal/src/app/config/scanner/config-scanner.component.ts @@ -1,7 +1,7 @@ import { Component, ViewChild, OnInit, OnDestroy } from "@angular/core"; import { Scanner } from "./scanner"; 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 { MessageHandlerService } from "../../shared/message-handler/message-handler.service"; import { ConfirmationButtons, ConfirmationState, ConfirmationTargets } from "../../shared/shared.const"; @@ -22,6 +22,7 @@ export class ConfigurationScannerComponent implements OnInit, OnDestroy { @ViewChild(NewScannerModalComponent, {static: false}) newScannerDialog: NewScannerModalComponent; deletionSubscription: any; + scannerDocUrl: string = SCANNERS_DOC; constructor( private configScannerService: ConfigScannerService, private errorHandler: ErrorHandler, diff --git a/src/portal/src/app/config/scanner/config-scanner.service.ts b/src/portal/src/app/config/scanner/config-scanner.service.ts index 4a05a7d77..40187177a 100644 --- a/src/portal/src/app/config/scanner/config-scanner.service.ts +++ b/src/portal/src/app/config/scanner/config-scanner.service.ts @@ -5,6 +5,8 @@ import { catchError, map } from "rxjs/operators"; import { HttpClient } from "@angular/common/http"; import { ScannerMetadata } from "./scanner-metadata"; +export const SCANNERS_DOC: string = "https://github.com/goharbor/harbor/blob/master/docs/harbor_compatibility_list.md"; + @Injectable() export class ConfigScannerService { diff --git a/src/portal/src/i18n/lang/en-us-lang.json b/src/portal/src/i18n/lang/en-us-lang.json index 9ecec4d1a..37feb4cb4 100644 --- a/src/portal/src/i18n/lang/en-us-lang.json +++ b/src/portal/src/i18n/lang/en-us-lang.json @@ -1346,6 +1346,12 @@ "CONFIRM_DELETION": "Confirm Scanner deletion", "NO_PROJECT_SCANNER": "No Scanner", "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." + } } diff --git a/src/portal/src/i18n/lang/es-es-lang.json b/src/portal/src/i18n/lang/es-es-lang.json index 80f4cb574..0d2d2811a 100644 --- a/src/portal/src/i18n/lang/es-es-lang.json +++ b/src/portal/src/i18n/lang/es-es-lang.json @@ -1343,6 +1343,11 @@ "CONFIRM_DELETION": "Confirm Scanner deletion", "NO_PROJECT_SCANNER": "No Scanner", "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." } } diff --git a/src/portal/src/i18n/lang/fr-fr-lang.json b/src/portal/src/i18n/lang/fr-fr-lang.json index 65de12155..8641652a5 100644 --- a/src/portal/src/i18n/lang/fr-fr-lang.json +++ b/src/portal/src/i18n/lang/fr-fr-lang.json @@ -1315,6 +1315,11 @@ "CONFIRM_DELETION": "Confirm Scanner deletion", "NO_PROJECT_SCANNER": "No Scanner", "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." } } diff --git a/src/portal/src/i18n/lang/pt-br-lang.json b/src/portal/src/i18n/lang/pt-br-lang.json index db3717812..eef1106d4 100644 --- a/src/portal/src/i18n/lang/pt-br-lang.json +++ b/src/portal/src/i18n/lang/pt-br-lang.json @@ -1340,7 +1340,12 @@ "CONFIRM_DELETION": "Confirm Scanner deletion", "NO_PROJECT_SCANNER": "No Scanner", "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." } } diff --git a/src/portal/src/i18n/lang/tr-tr-lang.json b/src/portal/src/i18n/lang/tr-tr-lang.json index 51451d4dc..4af159d0b 100644 --- a/src/portal/src/i18n/lang/tr-tr-lang.json +++ b/src/portal/src/i18n/lang/tr-tr-lang.json @@ -1345,6 +1345,11 @@ "CONFIRM_DELETION": "Confirm Scanner deletion", "NO_PROJECT_SCANNER": "No Scanner", "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." } } diff --git a/src/portal/src/i18n/lang/zh-cn-lang.json b/src/portal/src/i18n/lang/zh-cn-lang.json index 48ef5a083..56edaa004 100644 --- a/src/portal/src/i18n/lang/zh-cn-lang.json +++ b/src/portal/src/i18n/lang/zh-cn-lang.json @@ -1342,6 +1342,11 @@ "CONFIRM_DELETION": "删除扫描器确认", "NO_PROJECT_SCANNER": "无扫描器", "SET_UNHEALTHY_SCANNER": "选择的扫描器:{{name}}是不健康的", - "SCANNED_BY": "扫描器:" + "SCANNED_BY": "扫描器:", + "IMAGE_SCANNERS": "镜像扫描器", + "VIEW_DOC": "查看文档", + "ALL_SCANNERS": "全部扫描器", + "HELP_INFO_1": "默认扫描器已安装。获取扫描器安装帮助,请查看", + "HELP_INFO_2": "文档。" } } diff --git a/src/portal/src/lib/components/project-policy-config/project-policy-config.component.html b/src/portal/src/lib/components/project-policy-config/project-policy-config.component.html index 141901671..fe6108034 100644 --- a/src/portal/src/lib/components/project-policy-config/project-policy-config.component.html +++ b/src/portal/src/lib/components/project-policy-config/project-policy-config.component.html @@ -21,7 +21,7 @@ - +