diff --git a/src/ui_ng/lib/README.md b/src/ui_ng/lib/README.md index 01d46bac4..ce4796cd0 100644 --- a/src/ui_ng/lib/README.md +++ b/src/ui_ng/lib/README.md @@ -6,6 +6,7 @@ Wrap the following Harbor UI components into a sharable library and published as * Replication endpoints management view * Access log list view * Vulnerability scanning result bar chart and list view (Embedded in tag management view) +* Registry(Harbor) related configuration options The Harbor UI library is built on **[Angular ](https://angular.io/)** 4.x and **[Clarity ](https://vmware.github.io/clarity/)** 0.9.x . @@ -22,12 +23,20 @@ Execute the testing specs with command: npm run test ``` +Install the package +``` +npm install harbor-ui[@version] +``` + ## Usage **Add dependency to application** Execute install command to add dependency to package.json ``` npm install harbor-ui --save + +//OR +npm install harbor-ui@0.2.x --save ``` The latest version of the library will be installed. @@ -113,6 +122,16 @@ This view is linked by the repository stack view only when the Clair is enabled ``` ``` + +* **Registry related configuration** + +This component provides some options for registry(Harbor) related configurations. + +**hasAdminRole** is an @Input property to indicate if the current logged user has administrator role. + +``` + +``` ## Configurations All the related configurations are defined in the **HarborModuleConfig** interface. @@ -127,6 +146,7 @@ export const DefaultServiceConfig: IServiceConfig = { replicationRuleEndpoint: "/api/policies/replication", replicationJobEndpoint: "/api/jobs/replication", vulnerabilityScanningBaseEndpoint: "/api/repositories", + configurationEndpoint: "/api/configurations", enablei18Support: false, defaultLang: DEFAULT_LANG, //'en-us' langCookieKey: DEFAULT_LANG_COOKIE_KEY, //'harbor-lang' @@ -165,6 +185,8 @@ It supports partially overriding. For the items not overridden, default values w * **vulnerabilityScanningBaseEndpoint:** The base endpoint of the service used to handle the vulnerability scanning results.Default value is "/api/repositories". +* **configurationEndpoint:** The base endpoint of the service used to configure registry related options. Default is "/api/configurations". + * **langCookieKey:** The cookie key used to store the current used language preference. Default is "harbor-lang". * **supportedLangs:** Declare what languages are supported. Default is ['en-us', 'zh-cn', 'es-es']. @@ -254,7 +276,6 @@ export class MyAccessLogService extends AccessLogService { * - page * - pageSize * - * @abstract * @param {(number | string)} projectId * @param {RequestQueryParams} [queryParams] * @returns {(Observable | Promise | AccessLog[])} @@ -268,7 +289,6 @@ export class MyAccessLogService extends AccessLogService { /** * Get the recent logs. * - * @abstract * @param {number} lines : Specify how many lines should be returned. * @returns {(Observable | Promise | AccessLog[])} * @@ -295,7 +315,6 @@ export class MyEndpointService extends EndpointService { * Get all the endpoints. * Set the argument 'endpointName' to return only the endpoints match the name pattern. * - * @abstract * @param {string} [endpointName] * @param {RequestQueryParams} [queryParams] * @returns {(Observable | Endpoint[])} @@ -309,7 +328,6 @@ export class MyEndpointService extends EndpointService { /** * Get the specified endpoint. * - * @abstract * @param {(number | string)} endpointId * @returns {(Observable | Endpoint)} * @@ -322,7 +340,6 @@ export class MyEndpointService extends EndpointService { /** * Create new endpoint. * - * @abstract * @param {Endpoint} endpoint * @returns {(Observable | any)} * @@ -335,7 +352,6 @@ export class MyEndpointService extends EndpointService { /** * Update the specified endpoint. * - * @abstract * @param {(number | string)} endpointId * @param {Endpoint} endpoint * @returns {(Observable | any)} @@ -349,7 +365,6 @@ export class MyEndpointService extends EndpointService { /** * Delete the specified endpoint. * - * @abstract * @param {(number | string)} endpointId * @returns {(Observable | any)} * @@ -362,7 +377,6 @@ export class MyEndpointService extends EndpointService { /** * Ping the specified endpoint. * - * @abstract * @param {Endpoint} endpoint * @returns {(Observable | any)} * @@ -375,7 +389,6 @@ export class MyEndpointService extends EndpointService { /** * Check endpoint whether in used with specific replication rule. * - * @abstract * @param {{number | string}} endpointId * @returns {{Observable | any}} */ @@ -402,7 +415,6 @@ export class MyReplicationService extends ReplicationService { * set the argument 'ruleName' to return the rule only match the name pattern; * if pagination needed, use the queryParams to add query parameters. * - * @abstract * @param {(number | string)} [projectId] * @param {string} [ruleName] * @param {RequestQueryParams} [queryParams] @@ -417,7 +429,6 @@ export class MyReplicationService extends ReplicationService { /** * Get the specified replication rule. * - * @abstract * @param {(number | string)} ruleId * @returns {(Observable | Promise | ReplicationRule)} * @@ -430,7 +441,6 @@ export class MyReplicationService extends ReplicationService { /** * Create new replication rule. * - * @abstract * @param {ReplicationRule} replicationRule * @returns {(Observable | Promise | any)} * @@ -443,7 +453,6 @@ export class MyReplicationService extends ReplicationService { /** * Update the specified replication rule. * - * @abstract * @param {ReplicationRule} replicationRule * @returns {(Observable | Promise | any)} * @@ -456,7 +465,6 @@ export class MyReplicationService extends ReplicationService { /** * Delete the specified replication rule. * - * @abstract * @param {(number | string)} ruleId * @returns {(Observable | Promise | any)} * @@ -469,7 +477,6 @@ export class MyReplicationService extends ReplicationService { /** * Enable the specified replication rule. * - * @abstract * @param {(number | string)} ruleId * @returns {(Observable | Promise | any)} * @@ -482,7 +489,6 @@ export class MyReplicationService extends ReplicationService { /** * Disable the specified replication rule. * - * @abstract * @param {(number | string)} ruleId * @returns {(Observable | Promise | any)} * @@ -501,7 +507,6 @@ export class MyReplicationService extends ReplicationService { * - page * - pageSize * - * @abstract * @param {(number | string)} ruleId * @param {RequestQueryParams} [queryParams] * @returns {(Observable | Promise | ReplicationJob)} @@ -532,7 +537,6 @@ export class MyRepositoryService extends RepositoryService { * 'page': current page, * 'page_size': page size. * - * @abstract * @param {(number | string)} projectId * @param {string} repositoryName * @param {RequestQueryParams} [queryParams] @@ -547,7 +551,6 @@ export class MyRepositoryService extends RepositoryService { /** * DELETE the specified repository. * - * @abstract * @param {string} repositoryName * @returns {(Observable | Promise | any)} * @@ -572,8 +575,7 @@ export class MyTagService extends TagService { /** * Get all the tags under the specified repository. * NOTES: If the Notary is enabled, the signatures should be included in the returned data. - * - * @abstract + * * @param {string} repositoryName * @param {RequestQueryParams} [queryParams] * @returns {(Observable | Promise | Tag[])} @@ -587,7 +589,6 @@ export class MyTagService extends TagService { /** * Delete the specified tag. * - * @abstract * @param {string} repositoryName * @param {string} tag * @returns {(Observable | any)} @@ -614,14 +615,12 @@ HarborLibraryModule.forRoot({ * Get the vulnerabilities scanning results for the specified tag. * * @export - * @abstract * @class ScanningResultService */ export class MyScanningResultService extends ScanningResultService { /** * Get the summary of vulnerability scanning result. * - * @abstract * @param {string} tagId * @returns {(Observable | Promise | VulnerabilitySummary)} * @@ -634,7 +633,6 @@ export class MyScanningResultService extends ScanningResultService { /** * Get the detailed vulnerabilities scanning results. * - * @abstract * @param {string} tagId * @returns {(Observable | Promise | VulnerabilityItem[])} * @@ -648,7 +646,6 @@ export class MyScanningResultService extends ScanningResultService { /** * Start a new vulnerability scanning * - * @abstract * @param {string} repoName * @param {string} tagId * @returns {(Observable | Promise | any)} @@ -672,13 +669,11 @@ HarborLibraryModule.forRoot({ ``` /** * Get System information about current backend server. - * @abstract * @class */ export class MySystemInfoService extends SystemInfoService { /** * Get global system information. - * @abstract * @returns */ getSystemInfo(): Observable | Promise | SystemInfo { @@ -693,3 +688,46 @@ HarborLibraryModule.forRoot({ ... ``` + +* **ConfigurationService:** Get and save the registry related configuration options. + +``` +/** + * Service used to get and save registry-related configurations. + * + * @export + * @class MyConfigurationService + */ +export class MyConfigurationService extends ConfigurationService{ + + /** + * Get configurations. + * + + * @returns {(Observable | Promise | Configuration)} + * + * @memberOf ConfigurationService + */ + getConfigurations(): Observable | Promise | Configuration{ + ... + } + + /** + * Save configurations. + * + + * @returns {(Observable | Promise | Configuration)} + * + * @memberOf ConfigurationService + */ + saveConfigurations(changedConfigs: any | { [key: string]: any | any[] }): Observable | Promise | any{ + ... + } +} + +... +HarborLibraryModule.forRoot({ + config.configService || { provide: ConfigurationService, useClass: ConfigurationDefaultService } +}) +... +``` diff --git a/src/ui_ng/lib/src/config/registry-config.component.html.ts b/src/ui_ng/lib/src/config/registry-config.component.html.ts index 98c594fa8..a647ca0bb 100644 --- a/src/ui_ng/lib/src/config/registry-config.component.html.ts +++ b/src/ui_ng/lib/src/config/registry-config.component.html.ts @@ -1,8 +1,8 @@ export const REGISTRY_CONFIG_HTML: string = `
- - - + + +
diff --git a/src/ui_ng/lib/src/config/registry-config.component.spec.ts b/src/ui_ng/lib/src/config/registry-config.component.spec.ts index 65dfc83a3..c29041130 100644 --- a/src/ui_ng/lib/src/config/registry-config.component.spec.ts +++ b/src/ui_ng/lib/src/config/registry-config.component.spec.ts @@ -10,12 +10,15 @@ import { VulnerabilityConfigComponent } from './vulnerability/vulnerability-conf import { RegistryConfigComponent } from './registry-config.component'; import { ConfirmationDialogComponent } from '../confirmation-dialog/confirmation-dialog.component'; -import { - ConfigurationService, +import { + ConfigurationService, ConfigurationDefaultService, ScanningResultService, - ScanningResultDefaultService - } from '../service/index'; + ScanningResultDefaultService, + SystemInfoService, + SystemInfoDefaultService, + SystemInfo +} from '../service/index'; import { Configuration } from './config'; describe('RegistryConfigComponent (inline template)', () => { @@ -23,8 +26,10 @@ describe('RegistryConfigComponent (inline template)', () => { let comp: RegistryConfigComponent; let fixture: ComponentFixture; let cfgService: ConfigurationService; + let systemInfoService: SystemInfoService; let spy: jasmine.Spy; let saveSpy: jasmine.Spy; + let spySystemInfo: jasmine.Spy; let mockConfig: Configuration = new Configuration(); mockConfig.token_expiration.value = 90; mockConfig.verify_remote_cert.value = true; @@ -37,6 +42,18 @@ describe('RegistryConfigComponent (inline template)', () => { let config: IServiceConfig = { configurationEndpoint: '/api/configurations/testing' }; + let mockSystemInfo: SystemInfo = { + "with_notary": true, + "with_admiral": false, + "with_clair": true, + "admiral_endpoint": "NA", + "auth_mode": "db_auth", + "registry_url": "10.112.122.56", + "project_creation_restriction": "everyone", + "self_registration": true, + "has_ca_root": true, + "harbor_version": "v1.1.1-rc1-160-g565110d" + }; beforeEach(async(() => { TestBed.configureTestingModule({ @@ -54,7 +71,8 @@ describe('RegistryConfigComponent (inline template)', () => { ErrorHandler, { provide: SERVICE_CONFIG, useValue: config }, { provide: ConfigurationService, useClass: ConfigurationDefaultService }, - { provide: ScanningResultService, useClass: ScanningResultDefaultService } + { provide: ScanningResultService, useClass: ScanningResultDefaultService }, + { provide: SystemInfoService, useClass: SystemInfoDefaultService } ] }); })); @@ -64,30 +82,34 @@ describe('RegistryConfigComponent (inline template)', () => { comp = fixture.componentInstance; cfgService = fixture.debugElement.injector.get(ConfigurationService); + systemInfoService = fixture.debugElement.injector.get(SystemInfoService); spy = spyOn(cfgService, 'getConfigurations').and.returnValue(Promise.resolve(mockConfig)); saveSpy = spyOn(cfgService, 'saveConfigurations').and.returnValue(Promise.resolve(true)); + spySystemInfo = spyOn(systemInfoService, 'getSystemInfo').and.returnValues(Promise.resolve(mockSystemInfo)); fixture.detectChanges(); }); it('should render configurations to the view', async(() => { expect(spy.calls.count()).toEqual(1); + expect(spySystemInfo.calls.count()).toEqual(1); fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); let el: HTMLInputElement = fixture.nativeElement.querySelector('input[type="text"]'); - expect(el).toBeTruthy(); + expect(el).not.toBeFalsy(); expect(el.value).toEqual('30'); let el2: HTMLInputElement = fixture.nativeElement.querySelector('input[type="checkbox"]'); expect(el2).toBeTruthy(); expect(el2.value).toEqual('on'); + fixture.detectChanges(); let el3: HTMLInputElement = fixture.nativeElement.querySelector('input[type="time"]'); expect(el3).toBeTruthy(); - expect(el3.value).toBeTruthy(); + expect(el3).not.toBeFalsy(); }); })); diff --git a/src/ui_ng/lib/src/config/registry-config.component.ts b/src/ui_ng/lib/src/config/registry-config.component.ts index 49c61fbd4..d66de74c9 100644 --- a/src/ui_ng/lib/src/config/registry-config.component.ts +++ b/src/ui_ng/lib/src/config/registry-config.component.ts @@ -1,8 +1,8 @@ -import { Component, OnInit, EventEmitter, Output, ViewChild } from '@angular/core'; +import { Component, OnInit, EventEmitter, Output, ViewChild, Input } from '@angular/core'; import { Configuration, ComplexValueItem } from './config'; import { REGISTRY_CONFIG_HTML } from './registry-config.component.html'; -import { ConfigurationService } from '../service/index'; +import { ConfigurationService, SystemInfoService, SystemInfo } from '../service/index'; import { toPromise } from '../utils'; import { ErrorHandler } from '../error-handler'; import { @@ -26,6 +26,9 @@ export class RegistryConfigComponent implements OnInit { config: Configuration = new Configuration(); configCopy: Configuration; onGoing: boolean = false; + systemInfo: SystemInfo; + + @Input() hasAdminRole: boolean = false; @ViewChild("replicationConfig") replicationCfg: ReplicationConfigComponent; @ViewChild("systemSettings") systemSettings: SystemSettingsComponent; @@ -35,14 +38,28 @@ export class RegistryConfigComponent implements OnInit { constructor( private configService: ConfigurationService, private errorHandler: ErrorHandler, - private translate: TranslateService + private translate: TranslateService, + private systemInfoService: SystemInfoService ) { } get shouldDisable(): boolean { return !this.isValid() || !this.hasChanges() || this.onGoing; } + get hasCAFile(): boolean { + return this.systemInfo && this.systemInfo.has_ca_root; + } + + get withClair(): boolean { + return this.systemInfo && this.systemInfo.with_clair; + } + ngOnInit(): void { + //Get system info + toPromise(this.systemInfoService.getSystemInfo()) + .then((info: SystemInfo) => this.systemInfo = info) + .catch(error => this.errorHandler.error(error)); + //Initialize this.load(); } diff --git a/src/ui_ng/lib/src/config/replication/replication-config.component.html.ts b/src/ui_ng/lib/src/config/replication/replication-config.component.html.ts index ca6a701f1..52b081f6c 100644 --- a/src/ui_ng/lib/src/config/replication/replication-config.component.html.ts +++ b/src/ui_ng/lib/src/config/replication/replication-config.component.html.ts @@ -1,7 +1,7 @@ export const REPLICATION_CONFIG_HTML: string = `
- +
diff --git a/src/ui_ng/lib/src/config/replication/replication-config.component.ts b/src/ui_ng/lib/src/config/replication/replication-config.component.ts index 60c0dd1f3..c139e4b39 100644 --- a/src/ui_ng/lib/src/config/replication/replication-config.component.ts +++ b/src/ui_ng/lib/src/config/replication/replication-config.component.ts @@ -21,6 +21,8 @@ export class ReplicationConfigComponent { this.configChange.emit(this.config); } + @Input() showSubTitle: boolean = false + @ViewChild("replicationConfigFrom") replicationConfigForm: NgForm; get editable(): boolean { diff --git a/src/ui_ng/lib/src/config/system/system-settings.component.html.ts b/src/ui_ng/lib/src/config/system/system-settings.component.html.ts index d548f3530..25405aa88 100644 --- a/src/ui_ng/lib/src/config/system/system-settings.component.html.ts +++ b/src/ui_ng/lib/src/config/system/system-settings.component.html.ts @@ -1,7 +1,7 @@ export const SYSTEM_SETTINGS_HTML: string = `
- +
+
`; \ No newline at end of file diff --git a/src/ui_ng/lib/src/config/system/system-settings.component.ts b/src/ui_ng/lib/src/config/system/system-settings.component.ts index f2d174f7c..12aea9908 100644 --- a/src/ui_ng/lib/src/config/system/system-settings.component.ts +++ b/src/ui_ng/lib/src/config/system/system-settings.component.ts @@ -21,6 +21,10 @@ export class SystemSettingsComponent { this.configChange.emit(this.config); } + @Input() showSubTitle: boolean = false; + @Input() hasAdminRole: boolean = false; + @Input() hasCAFile: boolean = false; + @ViewChild("systemConfigFrom") systemSettingsForm: NgForm; get editable(): boolean { @@ -32,4 +36,8 @@ export class SystemSettingsComponent { get isValid(): boolean { return this.systemSettingsForm && this.systemSettingsForm.valid; } + + get canDownloadCert(): boolean { + return this.hasAdminRole && this.hasCAFile; + } } \ No newline at end of file diff --git a/src/ui_ng/lib/src/config/vulnerability/vulnerability-config.component.template.ts b/src/ui_ng/lib/src/config/vulnerability/vulnerability-config.component.template.ts index 361f4cb1b..f7c19ef5a 100644 --- a/src/ui_ng/lib/src/config/vulnerability/vulnerability-config.component.template.ts +++ b/src/ui_ng/lib/src/config/vulnerability/vulnerability-config.component.template.ts @@ -1,7 +1,7 @@ export const VULNERABILITY_CONFIG_HTML: string = `
- +
@@ -12,6 +12,10 @@ export const VULNERABILITY_CONFIG_HTML: string = `
+ + + {{'CONFIG.TOOLTIP.SCANNING_POLICY' | translate}} +
diff --git a/src/ui_ng/lib/src/config/vulnerability/vulnerability-config.component.ts b/src/ui_ng/lib/src/config/vulnerability/vulnerability-config.component.ts index b8cceb360..2dd09463c 100644 --- a/src/ui_ng/lib/src/config/vulnerability/vulnerability-config.component.ts +++ b/src/ui_ng/lib/src/config/vulnerability/vulnerability-config.component.ts @@ -41,6 +41,8 @@ export class VulnerabilityConfigComponent { this.configChange.emit(this.config); } + @Input() showSubTitle: boolean = false + //UTC time get dailyTime(): string { if (!(this.config && diff --git a/src/ui_ng/package.json b/src/ui_ng/package.json index 56b3f804d..2e1f8c052 100644 --- a/src/ui_ng/package.json +++ b/src/ui_ng/package.json @@ -31,7 +31,7 @@ "clarity-icons": "^0.9.8", "clarity-ui": "^0.9.8", "core-js": "^2.4.1", - "harbor-ui": "^0.2.52", + "harbor-ui": "^0.2.55", "intl": "^1.2.5", "mutationobserver-shim": "^0.3.2", "ngx-cookie": "^1.0.0", diff --git a/src/ui_ng/src/app/app-config.ts b/src/ui_ng/src/app/app-config.ts index a3166745b..f2595b2ac 100644 --- a/src/ui_ng/src/app/app-config.ts +++ b/src/ui_ng/src/app/app-config.ts @@ -16,6 +16,7 @@ export class AppConfig { //Set default value this.with_notary = false; this.with_admiral = false; + this.with_clair = false; this.admiral_endpoint = ""; this.auth_mode = "db_auth"; this.registry_url = ""; @@ -27,6 +28,7 @@ export class AppConfig { with_notary: boolean; with_admiral: boolean; + with_clair: boolean; admiral_endpoint: string; auth_mode: string; registry_url: string; diff --git a/src/ui_ng/src/app/config/config.component.html b/src/ui_ng/src/app/config/config.component.html index b5b19707f..cdc9f58c4 100644 --- a/src/ui_ng/src/app/config/config.component.html +++ b/src/ui_ng/src/app/config/config.component.html @@ -15,7 +15,7 @@ - @@ -29,9 +29,9 @@
- +
-
+
diff --git a/src/ui_ng/src/app/config/config.component.ts b/src/ui_ng/src/app/config/config.component.ts index f239e8d45..eeeffb885 100644 --- a/src/ui_ng/src/app/config/config.component.ts +++ b/src/ui_ng/src/app/config/config.component.ts @@ -71,6 +71,19 @@ export class ConfigurationComponent implements OnInit, OnDestroy { private appConfigService: AppConfigService, private session: SessionService) { } + public get hasAdminRole(): boolean { + return this.session.getCurrentUser() && + this.session.getCurrentUser().has_admin_role > 0; + } + + public get hasCAFile(): boolean { + return this.appConfigService.getConfig().has_ca_root; + } + + public get withClair(): boolean { + return this.appConfigService.getConfig().with_clair; + } + isCurrentTabLink(tabId: string): boolean { return this.currentTabId === tabId; } diff --git a/src/ui_ng/src/app/shared/list-project-ro/list-project-ro.component.ts b/src/ui_ng/src/app/shared/list-project-ro/list-project-ro.component.ts index 741c08a34..e8adc027d 100644 --- a/src/ui_ng/src/app/shared/list-project-ro/list-project-ro.component.ts +++ b/src/ui_ng/src/app/shared/list-project-ro/list-project-ro.component.ts @@ -40,7 +40,7 @@ export class ListProjectROComponent { goToLink(proId: number): void { this.searchTrigger.closeSearch(true); - let linkUrl = ['harbor', 'projects', proId, 'repository']; + let linkUrl = ['harbor', 'projects', proId, 'repositories']; this.router.navigate(linkUrl); } diff --git a/src/ui_ng/src/i18n/lang/en-us-lang.json b/src/ui_ng/src/i18n/lang/en-us-lang.json index e241087d7..2b48113ad 100644 --- a/src/ui_ng/src/i18n/lang/en-us-lang.json +++ b/src/ui_ng/src/i18n/lang/en-us-lang.json @@ -83,8 +83,7 @@ "PROFILE": "User Profile", "CHANGE_PWD": "Change Password", "ABOUT": "About", - "LOGOUT": "Log Out", - "ROOT_CERT": "Download Root Cert" + "LOGOUT": "Log Out" }, "GLOBAL_SEARCH": { "PLACEHOLDER": "Search Harbor...", @@ -383,6 +382,8 @@ "SCOPE_SUBTREE": "Subtree", "PRO_CREATION_EVERYONE": "Everyone", "PRO_CREATION_ADMIN": "Admin Only", + "ROOT_CERT": "Registry Root Certificate", + "ROOT_CERT_LINK": "Download", "TOOLTIP": { "SELF_REGISTRATION": "Enable sign up.", "VERIFY_REMOTE_CERT": "Determine whether the image replication should verify the certificate of a remote Harbor registry. Uncheck this box when the remote registry uses a self-signed or untrusted certificate.", @@ -390,9 +391,11 @@ "LDAP_SEARCH_DN": "A user's DN who has the permission to search the LDAP/AD server. If your LDAP/AD server does not support anonymous search, you should configure this DN and ldap_search_pwd.", "LDAP_BASE_DN": "The base DN from which to look up a user in LDAP/AD.", "LDAP_UID": "The attribute used in a search to match a user. It could be uid, cn, email, sAMAccountName or other attributes depending on your LDAP/AD.", - "LDAP_SCOPE": "The scope to search for users", + "LDAP_SCOPE": "The scope to search for users.", "TOKEN_EXPIRATION": "The expiration time (in minutes) of a token created by the token service. Default is 30 minutes.", - "PRO_CREATION_RESTRICTION": "The flag to define what users have permission to create projects. By default, everyone can create a project. Set to 'Admin Only' so that only an administrator can create a project." + "PRO_CREATION_RESTRICTION": "The flag to define what users have permission to create projects. By default, everyone can create a project. Set to 'Admin Only' so that only an administrator can create a project.", + "ROOT_CERT_DOWNLOAD": "Download the root certificate of registry.", + "SCANNING_POLICY": "Set image scanning policy based on different requirements. 'None': No active policy; 'Daily At': Triggering scanning at the specified time everyday; 'Upon Refresh': Triggering scanning when database refreshed." }, "LDAP": { "URL": "LDAP URL", diff --git a/src/ui_ng/src/i18n/lang/es-es-lang.json b/src/ui_ng/src/i18n/lang/es-es-lang.json index 8cd8f33a9..4f14ed47f 100644 --- a/src/ui_ng/src/i18n/lang/es-es-lang.json +++ b/src/ui_ng/src/i18n/lang/es-es-lang.json @@ -83,8 +83,7 @@ "PROFILE": "Perfil de usuario", "CHANGE_PWD": "Cambiar contraseña", "ABOUT": "Acerca de", - "LOGOUT": "Cerrar sesión", - "ROOT_CERT": "Descargar Certificado Raíz" + "LOGOUT": "Cerrar sesión" }, "GLOBAL_SEARCH": { "PLACEHOLDER": "Buscar en Harbor...", @@ -384,6 +383,8 @@ "SCOPE_SUBTREE": "Subárbol", "PRO_CREATION_EVERYONE": "Todos", "PRO_CREATION_ADMIN": "Solo Administradores", + "ROOT_CERT": "Registro Certificado Raíz", + "ROOT_CERT_LINK": "Descargar", "TOOLTIP": { "SELF_REGISTRATION": "Activar registro.", "VERIFY_REMOTE_CERT": "Determina si la replicación de la imagen debería verificar el certificado de un registro Harbor remoto. Desmarque esta opción cuando el registro remoto use un certificado de confianza o autofirmado.", @@ -393,7 +394,9 @@ "LDAP_UID": "El atributo usado en una búsqueda para encontrar un usuario. Debe ser el uid, cn, email, sAMAccountName u otro atributo dependiendo del LDAP/AD.", "LDAP_SCOPE": "El ámbito de búsqueda para usuarios", "TOKEN_EXPIRATION": "El tiempo de expiración (en minutos) del token creado por el servicio de tokens. Por defecto son 30 minutos.", - "PRO_CREATION_RESTRICTION": "Marca para definir qué usuarios tienen permisos para crear proyectos. Por defecto, todos pueden crear proyectos. Seleccione 'Solo Administradores' para que solamente los administradores puedan crear proyectos." + "PRO_CREATION_RESTRICTION": "Marca para definir qué usuarios tienen permisos para crear proyectos. Por defecto, todos pueden crear proyectos. Seleccione 'Solo Administradores' para que solamente los administradores puedan crear proyectos.", + "ROOT_CERT_DOWNLOAD": "Download the root certificate of registry.", + "SCANNING_POLICY": "Set image scanning policy based on different requirements. 'None': No active policy; 'Daily At': Triggering scanning at the specified time everyday; 'Upon Refresh': Triggering scanning when database refreshed." }, "LDAP": { "URL": "LDAP URL", diff --git a/src/ui_ng/src/i18n/lang/zh-cn-lang.json b/src/ui_ng/src/i18n/lang/zh-cn-lang.json index 1f79be8a7..7a64d09ae 100644 --- a/src/ui_ng/src/i18n/lang/zh-cn-lang.json +++ b/src/ui_ng/src/i18n/lang/zh-cn-lang.json @@ -83,8 +83,7 @@ "PROFILE": "用户设置", "CHANGE_PWD": "修改密码", "ABOUT": "关于", - "LOGOUT": "退出", - "ROOT_CERT": "下载根证书" + "LOGOUT": "退出" }, "GLOBAL_SEARCH": { "PLACEHOLDER": "搜索 Harbor...", @@ -383,6 +382,8 @@ "SCOPE_SUBTREE": "子树", "PRO_CREATION_EVERYONE": "所有人", "PRO_CREATION_ADMIN": "仅管理员", + "ROOT_CERT": "镜像库根证书", + "ROOT_CERT_LINK": "下载", "TOOLTIP": { "SELF_REGISTRATION": "激活注册功能。", "VERIFY_REMOTE_CERT": "确定镜像复制是否要验证远程Harbor实例的证书。如果远程实例使用的是自签或者非信任证书,不要勾选此项。", @@ -392,7 +393,9 @@ "LDAP_UID": "在搜索中用来匹配用户的属性,可以是uid,cn,email,sAMAccountName或者其它LDAP/AD服务器支持的属性。", "LDAP_SCOPE": "搜索用户的范围。", "TOKEN_EXPIRATION": "由令牌服务创建的令牌的过期时间(分钟),默认为30分钟。", - "PRO_CREATION_RESTRICTION": "用来确定哪些用户有权限创建项目,默认为’所有人‘,设置为’仅管理员‘则只有管理员可以创建项目。" + "PRO_CREATION_RESTRICTION": "用来确定哪些用户有权限创建项目,默认为’所有人‘,设置为’仅管理员‘则只有管理员可以创建项目。", + "ROOT_CERT_DOWNLOAD": "下载镜像库根证书.", + "SCANNING_POLICY": "基于不同需求设置镜像扫描策略。‘无’:不设置任何策略;‘每日定时’:每天在设置的时间定时执行扫描;‘缺陷库刷新后’:当缺陷数据库刷新后。" }, "LDAP": { "URL": "LDAP URL", @@ -409,7 +412,7 @@ "SCAN_ALL": "扫描所有", "SCAN_NOW": "开始扫描", "NONE_POLICY": "无", - "DAILY_POLICY": "每日", + "DAILY_POLICY": "每日定时", "REFRESH_POLICY": "缺陷库刷新后" }, "TEST_MAIL_SUCCESS": "邮件服务器的连通正常。",