From fd9e3dc2b88725cc2c593422dc9510023ee19350 Mon Sep 17 00:00:00 2001 From: Frank Kung Date: Fri, 12 Oct 2018 18:41:45 +0800 Subject: [PATCH 1/2] Add build history component to Harbor UI Add build histroy section and navbar to tag-detail component Add i18n items of build history Format code. Signed-off-by: Frank Kung --- src/portal/lib/src/service/interface.ts | 11 + src/portal/lib/src/service/tag.service.ts | 30 +- src/portal/lib/src/tag/index.ts | 15 +- .../lib/src/tag/tag-detail.component.html | 43 ++- .../lib/src/tag/tag-detail.component.ts | 257 ++++++++++-------- .../lib/src/tag/tag-history.component.html | 11 + .../lib/src/tag/tag-history.component.ts | 65 +++++ src/portal/package.json | 2 +- src/portal/src/i18n/lang/en-us-lang.json | 50 ++-- src/portal/src/i18n/lang/es-es-lang.json | 65 ++--- src/portal/src/i18n/lang/fr-fr-lang.json | 48 ++-- src/portal/src/i18n/lang/zh-cn-lang.json | 54 ++-- 12 files changed, 421 insertions(+), 230 deletions(-) create mode 100644 src/portal/lib/src/tag/tag-history.component.html create mode 100644 src/portal/lib/src/tag/tag-history.component.ts diff --git a/src/portal/lib/src/service/interface.ts b/src/portal/lib/src/service/interface.ts index ac32e4d2b..2aa87af68 100644 --- a/src/portal/lib/src/service/interface.ts +++ b/src/portal/lib/src/service/interface.ts @@ -382,3 +382,14 @@ export interface HelmChartSignature { signed: boolean; prov_file: string; } + +/** + * The manifest of image. + * + ** + * interface Manifest + */ +export interface Manifest { + manifset: Object; + config: string; +} diff --git a/src/portal/lib/src/service/tag.service.ts b/src/portal/lib/src/service/tag.service.ts index fdd9e7d93..fc738a262 100644 --- a/src/portal/lib/src/service/tag.service.ts +++ b/src/portal/lib/src/service/tag.service.ts @@ -9,7 +9,7 @@ import { HTTP_GET_OPTIONS } from "../utils"; import { RequestQueryParams } from "./RequestQueryParams"; -import { Tag } from "./interface"; +import { Tag, Manifest } from "./interface"; /** * For getting tag signatures. @@ -90,6 +90,19 @@ export abstract class TagService { tagName: string, labelId: number ): Observable | Promise | any; + + /** + * Get manifest of tag under the specified repository. + * + * @abstract + * returns {(Observable | Promise | Manifest)} + * + * @memberOf TagService + */ + abstract getManifest( + repositoryName: string, + tag: string + ): Observable | Promise | Manifest; } /** @@ -225,4 +238,19 @@ export class TagDefaultService extends TagService { .then(response => response.status) .catch(error => Promise.reject(error)); } + + public getManifest( + repositoryName: string, + tag: string + ): Observable | Promise | Manifest { + if (!repositoryName || !tag) { + return Promise.reject("Bad argument"); + } + let url: string = `${this._baseUrl}/${repositoryName}/tags/${tag}/manifest`; + return this.http + .get(url, HTTP_GET_OPTIONS) + .toPromise() + .then(response => response.json() as Manifest) + .catch(error => Promise.reject(error)); + } } diff --git a/src/portal/lib/src/tag/index.ts b/src/portal/lib/src/tag/index.ts index 2b876604c..08cf63cc2 100644 --- a/src/portal/lib/src/tag/index.ts +++ b/src/portal/lib/src/tag/index.ts @@ -1,11 +1,14 @@ -import { Type } from '@angular/core'; -import { TagComponent } from './tag.component'; -import { TagDetailComponent } from './tag-detail.component'; +import { Type } from "@angular/core"; +import { TagComponent } from "./tag.component"; +import { TagDetailComponent } from "./tag-detail.component"; +import { TagHistoryComponent } from "./tag-history.component"; -export * from './tag.component'; -export * from './tag-detail.component'; +export * from "./tag.component"; +export * from "./tag-detail.component"; +export * from "./tag-history.component"; export const TAG_DIRECTIVES: Type[] = [ TagComponent, - TagDetailComponent + TagDetailComponent, + TagHistoryComponent ]; diff --git a/src/portal/lib/src/tag/tag-detail.component.html b/src/portal/lib/src/tag/tag-detail.component.html index c391a5f0a..4e32960bb 100644 --- a/src/portal/lib/src/tag/tag-detail.component.html +++ b/src/portal/lib/src/tag/tag-detail.component.html @@ -20,7 +20,7 @@
{{tagDetails.architecture}}
-
+
{{tagDetails.os}}
@@ -42,17 +42,29 @@
-
- {{highCount}} {{packageText(highCount) | translate}} {{haveText(highCount) | translate}} {{'VULNERABILITY.SEVERITY.HIGH' | translate }} {{suffixForHigh | translate }}
+
+ +
+ {{highCount}} {{packageText(highCount) | translate}} {{haveText(highCount) | translate}} {{'VULNERABILITY.SEVERITY.HIGH' | translate }} {{suffixForHigh | translate }} +
-
- {{mediumCount}} {{packageText(mediumCount) | translate}} {{haveText(mediumCount) | translate}} {{'VULNERABILITY.SEVERITY.MEDIUM' | translate }} {{suffixForMedium | translate }}
+
+ +
+ {{mediumCount}} {{packageText(mediumCount) | translate}} {{haveText(mediumCount) | translate}} {{'VULNERABILITY.SEVERITY.MEDIUM' | translate }} {{suffixForMedium | translate }} +
-
- {{lowCount}} {{packageText(lowCount) | translate}} {{haveText(lowCount) | translate}} {{'VULNERABILITY.SEVERITY.LOW' | translate }} {{suffixForLow | translate }}
+
+ +
+ {{lowCount}} {{packageText(lowCount) | translate}} {{haveText(lowCount) | translate}} {{'VULNERABILITY.SEVERITY.LOW' | translate }} {{suffixForLow | translate }} +
-
- {{unknownCount}} {{packageText(unknownCount) | translate}} {{haveText(unknownCount) | translate}} {{'VULNERABILITY.SEVERITY.UNKNOWN' | translate }} {{suffixForUnknown | translate }}
+
+ +
+ {{unknownCount}} {{packageText(unknownCount) | translate}} {{haveText(unknownCount) | translate}} {{'VULNERABILITY.SEVERITY.UNKNOWN' | translate }} {{suffixForUnknown | translate }} + @@ -67,7 +79,15 @@
-
+ +
@@ -75,4 +95,7 @@
+
+ +
\ No newline at end of file diff --git a/src/portal/lib/src/tag/tag-detail.component.ts b/src/portal/lib/src/tag/tag-detail.component.ts index beba8aae9..888ad8beb 100644 --- a/src/portal/lib/src/tag/tag-detail.component.ts +++ b/src/portal/lib/src/tag/tag-detail.component.ts @@ -1,134 +1,175 @@ -import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core'; +import { Component, Input, Output, EventEmitter, OnInit } from "@angular/core"; -import { TagService, Tag, VulnerabilitySeverity } from '../service/index'; -import { toPromise } from '../utils'; -import { ErrorHandler } from '../error-handler/index'; -import {Label} from "../service/interface"; +import { TagService, Tag, VulnerabilitySeverity } from "../service/index"; +import { toPromise } from "../utils"; +import { ErrorHandler } from "../error-handler/index"; +import { Label } from "../service/interface"; + +const TabLinkContentMap: { [index: string]: string } = { + "tag-history": "history", + "tag-vulnerability": "vulnerability" +}; @Component({ - selector: 'hbr-tag-detail', - templateUrl: './tag-detail.component.html', - styleUrls: ['./tag-detail.component.scss'], + selector: "hbr-tag-detail", + templateUrl: "./tag-detail.component.html", + styleUrls: ["./tag-detail.component.scss"], - providers: [] + providers: [] }) export class TagDetailComponent implements OnInit { - _highCount: number = 0; - _mediumCount: number = 0; - _lowCount: number = 0; - _unknownCount: number = 0; - labels: Label; + _highCount: number = 0; + _mediumCount: number = 0; + _lowCount: number = 0; + _unknownCount: number = 0; + labels: Label; - @Input() tagId: string; - @Input() repositoryId: string; - @Input() withAdmiral: boolean; - @Input() withClair: boolean; - @Input() withAdminRole: boolean; - tagDetails: Tag = { - name: "--", - size: "--", - author: "--", - created: new Date(), - architecture: "--", - os: "--", - docker_version: "--", - digest: "--", - labels: [], - }; + @Input() + tagId: string; + @Input() + repositoryId: string; + @Input() + withAdmiral: boolean; + @Input() + withClair: boolean; + @Input() + withAdminRole: boolean; + tagDetails: Tag = { + name: "--", + size: "--", + author: "--", + created: new Date(), + architecture: "--", + os: "--", + docker_version: "--", + digest: "--", + labels: [] + }; - @Output() backEvt: EventEmitter = new EventEmitter(); + @Output() + backEvt: EventEmitter = new EventEmitter(); - constructor( - private tagService: TagService, - private errorHandler: ErrorHandler) { } + currentTabID = "tag-vulnerability"; - ngOnInit(): void { - if (this.repositoryId && this.tagId) { - toPromise(this.tagService.getTag(this.repositoryId, this.tagId)) - .then(response => { - this.tagDetails = response; - if (this.tagDetails && - this.tagDetails.scan_overview && - this.tagDetails.scan_overview.components && - this.tagDetails.scan_overview.components.summary) { - this.tagDetails.scan_overview.components.summary.forEach(item => { - switch (item.severity) { - case VulnerabilitySeverity.UNKNOWN: - this._unknownCount += item.count; - break; - case VulnerabilitySeverity.LOW: - this._lowCount += item.count; - break; - case VulnerabilitySeverity.MEDIUM: - this._mediumCount += item.count; - break; - case VulnerabilitySeverity.HIGH: - this._highCount += item.count; - break; - default: - break; - } - }); - } - }) - .catch(error => this.errorHandler.error(error)); - } + constructor( + private tagService: TagService, + private errorHandler: ErrorHandler + ) {} + + ngOnInit(): void { + if (this.repositoryId && this.tagId) { + toPromise(this.tagService.getTag(this.repositoryId, this.tagId)) + .then(response => { + this.tagDetails = response; + if ( + this.tagDetails && + this.tagDetails.scan_overview && + this.tagDetails.scan_overview.components && + this.tagDetails.scan_overview.components.summary + ) { + this.tagDetails.scan_overview.components.summary.forEach(item => { + switch (item.severity) { + case VulnerabilitySeverity.UNKNOWN: + this._unknownCount += item.count; + break; + case VulnerabilitySeverity.LOW: + this._lowCount += item.count; + break; + case VulnerabilitySeverity.MEDIUM: + this._mediumCount += item.count; + break; + case VulnerabilitySeverity.HIGH: + this._highCount += item.count; + break; + default: + break; + } + }); + } + }) + .catch(error => this.errorHandler.error(error)); } + } - onBack(): void { - this.backEvt.emit(this.repositoryId); - } + onBack(): void { + this.backEvt.emit(this.repositoryId); + } - getPackageText(count: number): string { - return count > 1 ? "VULNERABILITY.PACKAGES" : "VULNERABILITY.PACKAGE"; - } + getPackageText(count: number): string { + return count > 1 ? "VULNERABILITY.PACKAGES" : "VULNERABILITY.PACKAGE"; + } - packageText(count: number): string { - return count > 1 ? "VULNERABILITY.GRID.COLUMN_PACKAGES" : "VULNERABILITY.GRID.COLUMN_PACKAGE"; - } + packageText(count: number): string { + return count > 1 + ? "VULNERABILITY.GRID.COLUMN_PACKAGES" + : "VULNERABILITY.GRID.COLUMN_PACKAGE"; + } - haveText(count: number): string { - return count > 1 ? "TAG.HAVE" : "TAG.HAS"; - } + haveText(count: number): string { + return count > 1 ? "TAG.HAVE" : "TAG.HAS"; + } - public get author(): string { - return this.tagDetails && this.tagDetails.author ? this.tagDetails.author : 'TAG.ANONYMITY'; - } + public get author(): string { + return this.tagDetails && this.tagDetails.author + ? this.tagDetails.author + : "TAG.ANONYMITY"; + } - public get highCount(): number { - return this._highCount; - } + public get highCount(): number { + return this._highCount; + } - public get mediumCount(): number { - return this._mediumCount; - } + public get mediumCount(): number { + return this._mediumCount; + } - public get lowCount(): number { - return this._lowCount; - } + public get lowCount(): number { + return this._lowCount; + } - public get unknownCount(): number { - return this._unknownCount; - } + public get unknownCount(): number { + return this._unknownCount; + } - public get scanCompletedDatetime(): Date { - return this.tagDetails && this.tagDetails.scan_overview ? - this.tagDetails.scan_overview.update_time : null; - } + public get scanCompletedDatetime(): Date { + return this.tagDetails && this.tagDetails.scan_overview + ? this.tagDetails.scan_overview.update_time + : null; + } - public get suffixForHigh(): string { - return this.highCount > 1 ? "VULNERABILITY.PLURAL" : "VULNERABILITY.SINGULAR"; - } + public get suffixForHigh(): string { + return this.highCount > 1 + ? "VULNERABILITY.PLURAL" + : "VULNERABILITY.SINGULAR"; + } - public get suffixForMedium(): string { - return this.mediumCount > 1 ? "VULNERABILITY.PLURAL" : "VULNERABILITY.SINGULAR"; - } + public get suffixForMedium(): string { + return this.mediumCount > 1 + ? "VULNERABILITY.PLURAL" + : "VULNERABILITY.SINGULAR"; + } - public get suffixForLow(): string { - return this.lowCount > 1 ? "VULNERABILITY.PLURAL" : "VULNERABILITY.SINGULAR"; - } + public get suffixForLow(): string { + return this.lowCount > 1 + ? "VULNERABILITY.PLURAL" + : "VULNERABILITY.SINGULAR"; + } - public get suffixForUnknown(): string { - return this.unknownCount > 1 ? "VULNERABILITY.PLURAL" : "VULNERABILITY.SINGULAR"; - } + public get suffixForUnknown(): string { + return this.unknownCount > 1 + ? "VULNERABILITY.PLURAL" + : "VULNERABILITY.SINGULAR"; + } + + isCurrentTabLink(tabID: string): boolean { + return this.currentTabID === tabID; + } + + isCurrentTabContent(ContentID: string): boolean { + return TabLinkContentMap[this.currentTabID] === ContentID; + } + + tabLinkClick(tabID: string) { + this.currentTabID = tabID; + } } diff --git a/src/portal/lib/src/tag/tag-history.component.html b/src/portal/lib/src/tag/tag-history.component.html new file mode 100644 index 000000000..9d18fbf27 --- /dev/null +++ b/src/portal/lib/src/tag/tag-history.component.html @@ -0,0 +1,11 @@ + + {{ 'TAG.CREATION' | translate }} + {{ 'TAG.COMMAND' | translate }} + + + {{ h.created | date: 'short' }} + {{ h.created_by }} + + + {{ history.length }} commands + \ No newline at end of file diff --git a/src/portal/lib/src/tag/tag-history.component.ts b/src/portal/lib/src/tag/tag-history.component.ts new file mode 100644 index 000000000..6e9f3da50 --- /dev/null +++ b/src/portal/lib/src/tag/tag-history.component.ts @@ -0,0 +1,65 @@ +import { Component, Input, Output, EventEmitter, OnInit } from "@angular/core"; +import { TagService, Manifest } from "../service/index"; +import { toPromise } from "../utils"; +import { ErrorHandler } from "../error-handler/index"; + +@Component({ + selector: "hbr-tag-history", + templateUrl: "./tag-history.component.html", + + providers: [] +}) +export class TagHistoryComponent implements OnInit { + @Input() + tagId: string; + @Input() + repositoryId: string; + + @Output() + backEvt: EventEmitter = new EventEmitter(); + + config: any = {}; + history: Object[] = []; + loading: Boolean = false; + + constructor( + private tagService: TagService, + private errorHandler: ErrorHandler + ) {} + + ngOnInit(): void { + if (this.repositoryId && this.tagId) { + this.retrieve(this.repositoryId, this.tagId); + } + } + + retrieve(repositoryId: string, tagId: string) { + this.loading = true; + toPromise( + this.tagService.getManifest(this.repositoryId, this.tagId) + ) + .then(data => { + this.config = JSON.parse(data.config); + this.config.history.forEach((ele: any) => { + if (ele.created_by !== undefined) { + ele.created_by = ele.created_by + .replace("/bin/sh -c #(nop)", "") + .trimLeft() + .replace("/bin/sh -c", "RUN"); + } else { + ele.created_by = ele.comment; + } + this.history.push(ele); + }); + this.loading = false; + }) + .catch(error => { + this.errorHandler.error(error); + this.loading = false; + }); + } + + onBack(): void { + this.backEvt.emit(this.tagId); + } +} diff --git a/src/portal/package.json b/src/portal/package.json index 779e11b26..e6f654726 100644 --- a/src/portal/package.json +++ b/src/portal/package.json @@ -16,7 +16,7 @@ "npm_pack": "cd lib/dist && npm pack", "package": "npm run build_lib && npm run npm_pack", "link_lib": "cd lib/dist && npm link && cd ../../ && npm link @harbor/ui", - "build_all":"npm run build_lib && npm run link_lib && npm run build" + "build_all": "npm run build_lib && npm run link_lib && npm run build" }, "private": true, "dependencies": { diff --git a/src/portal/src/i18n/lang/en-us-lang.json b/src/portal/src/i18n/lang/en-us-lang.json index 6523aec38..919b7c78f 100644 --- a/src/portal/src/i18n/lang/en-us-lang.json +++ b/src/portal/src/i18n/lang/en-us-lang.json @@ -379,15 +379,15 @@ "IMMEDIATE": "Immediate", "DAILY": "Daily", "WEEKLY": "Weekly", - "SETTING":"Options", - "TRIGGER":"Triggering Condition", - "TARGETS":"Target", + "SETTING": "Options", + "TRIGGER": "Triggering Condition", + "TARGETS": "Target", "MODE": "Mode", "TRIGGER_MODE": "Trigger Mode", "SOURCE_PROJECT": "Source project", "REPLICATE": "Replicate", - "DELETE_REMOTE_IMAGES":"Delete remote images when locally deleted", - "REPLICATE_IMMEDIATE":"Replicate existing images immediately", + "DELETE_REMOTE_IMAGES": "Delete remote images when locally deleted", + "REPLICATE_IMMEDIATE": "Replicate existing images immediately", "NEW": "New", "NAME_TOOLTIP": "replication rule name should be at least 2 characters long with lower case characters, numbers and ._- and must be start with characters or numbers.", "DELETED_LABEL_INFO": "Deleted label(s) '{{param}}' referenced in the filter, click 'SAVE' to update the filter to enable this rule.", @@ -447,6 +447,7 @@ "TAG": "Tag", "SIZE": "Size", "VULNERABILITY": "Vulnerability", + "BUILD_HISTORY": "Build History", "SIGNED": "Signed", "AUTHOR": "Author", "CREATED": "Creation Time", @@ -753,7 +754,9 @@ "COPY_ERROR": "Copy failed, please try to manually copy.", "FILTER_FOR_TAGS": "Filter Tags", "AUTHOR": "Author", - "LABELS": "Labels" + "LABELS": "Labels", + "CREATION": "Create on", + "COMMAND": "Commands" }, "LABEL": { "LABEL": "Label", @@ -818,33 +821,32 @@ "SERVER_ERROR": "We are unable to perform your action because internal server errors have occurred.", "INCONRRECT_OLD_PWD": "The old password is incorrect.", "UNKNOWN": "n/a", - "STATUS":"Status", + "STATUS": "Status", "START_TIME": "Start Time", - "UPDATE_TIME": "Update Time", - "LOGS":"Logs", - "PENDING":"Pending", - "FINISHED":"Finished", - "STOPPED":"Stopped", - "RUNNING":"Running", - "ERROR":"Error", + "END_TIME": "End Time", + "DETAILS": "Details", + "PENDING": "Pending", + "FINISHED": "Finished", + "STOPPED": "Stopped", + "RUNNING": "Running", + "ERROR": "Error", "SCHEDULE": { "NONE": "None", "DAILY": "Daily", "WEEKLY": "Weekly", - "MANUAL": "Manual", - "ON": "on", - "AT": "at" - }, + "MANUAL": "Manual" + }, "GC": { "CURRENT_SCHEDULE": "Current Schedule", "GC_NOW": "GC NOW", - "JOB_HISTORY":"GC Jobs History", - "JOB_ID":"Job ID", + "JOB_LIST": "GC Jobs List", + "JOB_ID": "Job ID", "TRIGGER_TYPE": "Trigger Type", "LATEST_JOBS": "Latest {{param}} Jobs", - "MSG_SUCCESS":"Garbage Collection Successful", - "MSG_SCHEDULE_SET":"Garbage Collection schedule has been set", - "MSG_SCHEDULE_RESET":"Garbage Collection schedule has been reset" + "LOG_DETAIL": "Log Details", + "MSG_SUCCESS": "Garbage Collection Successful", + "MSG_SCHEDULE_SET": "Garbage Collection schedule has been set", + "MSG_SCHEDULE_RESET": "Garbage Collection schedule has been reset" } - + } diff --git a/src/portal/src/i18n/lang/es-es-lang.json b/src/portal/src/i18n/lang/es-es-lang.json index 9325dcf00..13122e322 100644 --- a/src/portal/src/i18n/lang/es-es-lang.json +++ b/src/portal/src/i18n/lang/es-es-lang.json @@ -378,15 +378,15 @@ "IMMEDIATE": "Immediate", "DAILY": "Daily", "WEEKLY": "Weekly", - "SETTING":"Options", - "TRIGGER":"Triggering Condition", - "TARGETS":"Target", + "SETTING": "Options", + "TRIGGER": "Triggering Condition", + "TARGETS": "Target", "MODE": "Mode", "TRIGGER_MODE": "Trigger Mode", "SOURCE_PROJECT": "Source project", "REPLICATE": "Replicate", - "DELETE_REMOTE_IMAGES":"Delete remote images when locally deleted", - "REPLICATE_IMMEDIATE":"Replicate existing images immediately", + "DELETE_REMOTE_IMAGES": "Delete remote images when locally deleted", + "REPLICATE_IMMEDIATE": "Replicate existing images immediately", "NEW": "New", "NAME_TOOLTIP": "replication rule name should be at least 2 characters long with lower case characters, numbers and ._- and must be start with characters or numbers.", "DELETED_LABEL_INFO": "Deleted label(s) '{{param}}' referenced in the filter, click 'SAVE' to update the filter to enable this rule.", @@ -446,6 +446,7 @@ "TAG": "Etiqueta", "SIZE": "Size", "VULNERABILITY": "Vulnerability", + "BUILD_HISTORY": "Construir Historia", "SIGNED": "Firmada", "AUTHOR": "Autor", "CREATED": "Fecha de creación", @@ -752,7 +753,10 @@ "COPY_ERROR": "Copy failed, please try to manually copy.", "FILTER_FOR_TAGS": "Etiquetas de filtro", "AUTHOR": "Author", - "LABELS": "Labels" + "LABELS": "Labels", + "CREATION": "Tiempo de creación", + "COMMAND": "Mando" + }, "LABEL": { "LABEL": "Label", @@ -771,13 +775,13 @@ "NAME_ALREADY_EXISTS": "Label name already exists." }, "WEEKLY": { - "MONDAY": "Monday", - "TUESDAY": "Tuesday", - "WEDNESDAY": "Wednesday", - "THURSDAY": "Thursday", - "FRIDAY": "Friday", - "SATURDAY": "Saturday", - "SUNDAY": "Sunday" + "MONDAY": "Monday", + "TUESDAY": "Tuesday", + "WEDNESDAY": "Wednesday", + "THURSDAY": "Thursday", + "FRIDAY": "Friday", + "SATURDAY": "Saturday", + "SUNDAY": "Sunday" }, "OPERATION": { "LOCAL_EVENT": "Local Events", @@ -815,32 +819,31 @@ "SERVER_ERROR": "No hemos podido llevar a cabo la acción debido a un error interno.", "INCONRRECT_OLD_PWD": "La contraseña antigua no es correcta.", "UNKNOWN": "n/a", - "STATUS":"Status", + "STATUS": "Status", "START_TIME": "Start Time", - "UPDATE_TIME": "Update Time", - "LOGS":"Logs", - "PENDING":"Pending", - "FINISHED":"Finished", - "STOPPED":"Stopped", - "RUNNING":"Running", - "ERROR":"Error", + "END_TIME": "End Time", + "DETAILS": "Details", + "PENDING": "Pending", + "FINISHED": "Finished", + "STOPPED": "Stopped", + "RUNNING": "Running", + "ERROR": "Error", "SCHEDULE": { "NONE": "None", "DAILY": "Daily", "WEEKLY": "Weekly", - "MANUAL": "Manual", - "ON": "on", - "AT": "at" - }, + "MANUAL": "Manual" + }, "GC": { "CURRENT_SCHEDULE": "Current Schedule", "GC_NOW": "GC NOW", - "JOB_HISTORY":"GC Jobs History", - "JOB_ID":"Job ID", + "JOB_LIST": "GC Jobs List", + "JOB_ID": "Job ID", "TRIGGER_TYPE": "Trigger Type", "LATEST_JOBS": "Latest {{param}} Jobs", - "MSG_SUCCESS":"Garbage Collection Successful", - "MSG_SCHEDULE_SET":"Garbage Collection schedule has been set", - "MSG_SCHEDULE_RESET":"Garbage Collection schedule has been reset" + "LOG_DETAIL": "Log Details", + "MSG_SUCCESS": "Garbage Collection Successful", + "MSG_SCHEDULE_SET": "Garbage Collection schedule has been set", + "MSG_SCHEDULE_RESET": "Garbage Collection schedule has been reset" } -} \ No newline at end of file +} diff --git a/src/portal/src/i18n/lang/fr-fr-lang.json b/src/portal/src/i18n/lang/fr-fr-lang.json index 1eec7e86a..89b146127 100644 --- a/src/portal/src/i18n/lang/fr-fr-lang.json +++ b/src/portal/src/i18n/lang/fr-fr-lang.json @@ -359,15 +359,15 @@ "IMMEDIATE": "Immediate", "DAILY": "Daily", "WEEKLY": "Weekly", - "SETTING":"Options", - "TRIGGER":"Triggering Condition", - "TARGETS":"Target", + "SETTING": "Options", + "TRIGGER": "Triggering Condition", + "TARGETS": "Target", "MODE": "Mode", "TRIGGER_MODE": "Trigger Mode", "SOURCE_PROJECT": "Source project", "REPLICATE": "Replicate", - "DELETE_REMOTE_IMAGES":"Delete remote images when locally deleted", - "REPLICATE_IMMEDIATE":"Replicate existing images immediately", + "DELETE_REMOTE_IMAGES": "Delete remote images when locally deleted", + "REPLICATE_IMMEDIATE": "Replicate existing images immediately", "NEW": "New", "NAME_TOOLTIP": "replication rule name should be at least 2 characters long with lower case characters, numbers and ._- and must be start with characters or numbers.", "DELETED_LABEL_INFO": "Deleted label(s) '{{param}}' referenced in the filter, click 'SAVE' to update the filter to enable this rule.", @@ -426,6 +426,7 @@ "TAG": "Tag", "SIZE": "Taille", "VULNERABILITY": "Vulnérabilitée", + "BUILD_HISTORY": "Construire l'histoire", "SIGNED": "Signé", "AUTHOR": "Auteur", "CREATED": "Heure de Création", @@ -716,7 +717,9 @@ "COPY_ERROR": "Copie échouée, veuillez essayer de copier manuellement.", "FILTER_FOR_TAGS": "Filter Tags", "AUTHOR": "Author", - "LABELS": "Labels" + "LABELS": "Labels", + "CREATION": "Créer sur", + "COMMAND": "Les commandes" }, "LABEL": { "LABEL": "Label", @@ -779,32 +782,31 @@ "SERVER_ERROR": "Nous ne sommes pas en mesure d'exécuter votre action parce que des erreurs internes de serveur se sont produites.", "INCONRRECT_OLD_PWD": "L'ancien mot de passe est incorrect.", "UNKNOWN": "n. d.", - "STATUS":"Status", + "STATUS": "Status", "START_TIME": "Start Time", - "UPDATE_TIME": "Update Time", - "LOGS":"Logs", - "PENDING":"Pending", - "FINISHED":"Finished", - "STOPPED":"Stopped", - "RUNNING":"Running", - "ERROR":"Error", + "END_TIME": "End Time", + "DETAILS": "Details", + "PENDING": "Pending", + "FINISHED": "Finished", + "STOPPED": "Stopped", + "RUNNING": "Running", + "ERROR": "Error", "SCHEDULE": { "NONE": "None", "DAILY": "Daily", "WEEKLY": "Weekly", - "MANUAL": "Manual", - "ON": "on", - "AT": "at" - }, + "MANUAL": "Manual" + }, "GC": { "CURRENT_SCHEDULE": "Current Schedule", "GC_NOW": "GC NOW", - "JOB_HISTORY":"GC Jobs History", - "JOB_ID":"Job ID", + "JOB_LIST": "GC Jobs List", + "JOB_ID": "Job ID", "TRIGGER_TYPE": "Trigger Type", "LATEST_JOBS": "Latest {{param}} Jobs", - "MSG_SUCCESS":"Garbage Collection Successful", - "MSG_SCHEDULE_SET":"Garbage Collection schedule has been set", - "MSG_SCHEDULE_RESET":"Garbage Collection schedule has been reset" + "LOG_DETAIL": "Log Details", + "MSG_SUCCESS": "Garbage Collection Successful", + "MSG_SCHEDULE_SET": "Garbage Collection schedule has been set", + "MSG_SCHEDULE_RESET": "Garbage Collection schedule has been reset" } } diff --git a/src/portal/src/i18n/lang/zh-cn-lang.json b/src/portal/src/i18n/lang/zh-cn-lang.json index 38c86be67..93efb98b2 100644 --- a/src/portal/src/i18n/lang/zh-cn-lang.json +++ b/src/portal/src/i18n/lang/zh-cn-lang.json @@ -378,15 +378,15 @@ "IMMEDIATE": "即刻", "DAILY": "每天", "WEEKLY": "每周", - "SETTING":"设置", - "TRIGGER":"触发条件", - "TARGETS":"目标", + "SETTING": "设置", + "TRIGGER": "触发条件", + "TARGETS": "目标", "MODE": "模式", "TRIGGER_MODE": "触发模式", "SOURCE_PROJECT": "源项目", "REPLICATE": "复制", - "DELETE_REMOTE_IMAGES":"删除本地镜像时同时也删除远程的镜像。", - "REPLICATE_IMMEDIATE":"立即复制现有的镜像。", + "DELETE_REMOTE_IMAGES": "删除本地镜像时同时也删除远程的镜像。", + "REPLICATE_IMMEDIATE": "立即复制现有的镜像。", "NEW": "新增", "NAME_TOOLTIP": "项目名称由小写字符、数字和._-组成且至少2个字符并以字符或者数字开头。", "DELETED_LABEL_INFO": "过滤项有被删除的标签 {{param}} , 点击保存按钮更新过滤项使规则可用。", @@ -446,6 +446,7 @@ "TAG": "标签", "SIZE": "大小", "VULNERABILITY": "漏洞", + "BUILD_HISTORY": "构建历史", "SIGNED": "已签名", "AUTHOR": "作者", "CREATED": "创建时间", @@ -751,7 +752,9 @@ "COPY_ERROR": "拷贝失败,请尝试手动拷贝。", "FILTER_FOR_TAGS": "过滤项目", "AUTHOR": "作者", - "LABELS": "标签" + "LABELS": "标签", + "CREATION": "创建时间", + "COMMAND": "命令" }, "LABEL": { "LABEL": "标签", @@ -764,7 +767,7 @@ "COLOR": "颜色", "FILTER_Label_PLACEHOLDER": "过滤标签", "NO_LABELS": "无标签", - "DELETION_TITLE_TARGET":"删除标签确认", + "DELETION_TITLE_TARGET": "删除标签确认", "DELETION_SUMMARY_TARGET": "确认删除标签 {{param}}?", "PLACEHOLDER": "未发现任何标签!", "NAME_ALREADY_EXISTS": "标签名已存在。" @@ -814,32 +817,31 @@ "SERVER_ERROR": "服务器出现内部错误,请求无法完成。", "INCONRRECT_OLD_PWD": "旧密码不正确。", "UNKNOWN": "未知", - "STATUS":"状态", - "START_TIME": "创建时间", - "UPDATE_TIME": "更新时间", - "LOGS":"日志", - "PENDING":"未开始", - "FINISHED":"已完成", - "STOPPED":"已停止", - "RUNNING":"执行中", - "ERROR":"错误", + "STATUS": "状态", + "START_TIME": "开始时间", + "END_TIME": "结束时间", + "DETAILS": "详情", + "PENDING": "未开始", + "FINISHED": "已完成", + "STOPPED": "已停止", + "RUNNING": "执行中", + "ERROR": "错误", "SCHEDULE": { "NONE": "无", "DAILY": "每天", "WEEKLY": "每周", - "MANUAL": "手动", - "ON": " ", - "AT": " " - }, + "MANUAL": "手动" + }, "GC": { "CURRENT_SCHEDULE": "当前定时任务", "GC_NOW": "立即清理垃圾", - "JOB_HISTORY":"历史任务", - "JOB_ID":"任务ID", + "JOB_LIST": "任务列表", + "JOB_ID": "任务ID", "TRIGGER_TYPE": "触发类型", "LATEST_JOBS": "最新的 {{param}} 个任务", - "MSG_SUCCESS":"垃圾回收成功", - "MSG_SCHEDULE_SET":"垃圾回收定时任务设置成功", - "MSG_SCHEDULE_RESET":"垃圾回收定时任务已被重置" + "LOG_DETAIL": "日志详情", + "MSG_SUCCESS": "垃圾回收成功", + "MSG_SCHEDULE_SET": "垃圾回收定时任务设置成功", + "MSG_SCHEDULE_RESET": "垃圾回收定时任务已被重置" } -} \ No newline at end of file +} From 735ae1b2f61fbd67c8c724cd9ba812b1a7ddde7a Mon Sep 17 00:00:00 2001 From: Frank Kung Date: Mon, 15 Oct 2018 22:42:16 +0800 Subject: [PATCH 2/2] Add unit test of build history section. Move style to scss file. Signed-off-by: Frank Kung --- .../lib/src/tag/tag-detail.component.spec.ts | 178 ++++++++++++------ .../lib/src/tag/tag-history.component.html | 2 +- .../lib/src/tag/tag-history.component.scss | 3 + .../lib/src/tag/tag-history.component.ts | 1 + src/portal/src/i18n/lang/en-us-lang.json | 11 +- src/portal/src/i18n/lang/es-es-lang.json | 11 +- src/portal/src/i18n/lang/fr-fr-lang.json | 11 +- src/portal/src/i18n/lang/zh-cn-lang.json | 13 +- 8 files changed, 148 insertions(+), 82 deletions(-) create mode 100644 src/portal/lib/src/tag/tag-history.component.scss diff --git a/src/portal/lib/src/tag/tag-detail.component.spec.ts b/src/portal/lib/src/tag/tag-detail.component.spec.ts index 1528c7098..e992c5326 100644 --- a/src/portal/lib/src/tag/tag-detail.component.spec.ts +++ b/src/portal/lib/src/tag/tag-detail.component.spec.ts @@ -1,89 +1,118 @@ -import { ComponentFixture, TestBed, async } from '@angular/core/testing'; +import { ComponentFixture, TestBed, async } from "@angular/core/testing"; -import { SharedModule } from '../shared/shared.module'; -import { ResultGridComponent } from '../vulnerability-scanning/result-grid.component'; -import { TagDetailComponent } from './tag-detail.component'; +import { SharedModule } from "../shared/shared.module"; +import { ResultGridComponent } from "../vulnerability-scanning/result-grid.component"; +import { TagDetailComponent } from "./tag-detail.component"; +import { TagHistoryComponent } from "./tag-history.component"; -import { ErrorHandler } from '../error-handler/error-handler'; -import { Tag, VulnerabilitySummary, VulnerabilityItem, VulnerabilitySeverity } from '../service/interface'; -import { SERVICE_CONFIG, IServiceConfig } from '../service.config'; -import { TagService, TagDefaultService, ScanningResultService, ScanningResultDefaultService } from '../service/index'; -import { FilterComponent } from '../filter/index'; -import { VULNERABILITY_SCAN_STATUS } from '../utils'; -import {VULNERABILITY_DIRECTIVES} from "../vulnerability-scanning/index"; -import {LabelPieceComponent} from "../label-piece/label-piece.component"; -import {JobLogViewerComponent} from "../job-log-viewer/job-log-viewer.component"; -import {ChannelService} from "../channel/channel.service"; -import {JobLogService, JobLogDefaultService} from "../service/job-log.service"; - -describe('TagDetailComponent (inline template)', () => { +import { ErrorHandler } from "../error-handler/error-handler"; +import { + Tag, + Manifest, + VulnerabilitySummary, + VulnerabilityItem, + VulnerabilitySeverity +} from "../service/interface"; +import { SERVICE_CONFIG, IServiceConfig } from "../service.config"; +import { + TagService, + TagDefaultService, + ScanningResultService, + ScanningResultDefaultService +} from "../service/index"; +import { FilterComponent } from "../filter/index"; +import { VULNERABILITY_SCAN_STATUS } from "../utils"; +import { VULNERABILITY_DIRECTIVES } from "../vulnerability-scanning/index"; +import { LabelPieceComponent } from "../label-piece/label-piece.component"; +import { JobLogViewerComponent } from "../job-log-viewer/job-log-viewer.component"; +import { ChannelService } from "../channel/channel.service"; +import { + JobLogService, + JobLogDefaultService +} from "../service/job-log.service"; +describe("TagDetailComponent (inline template)", () => { let comp: TagDetailComponent; let fixture: ComponentFixture; let tagService: TagService; let scanningService: ScanningResultService; let spy: jasmine.Spy; let vulSpy: jasmine.Spy; + let manifestSpy: jasmine.Spy; let mockVulnerability: VulnerabilitySummary = { scan_status: VULNERABILITY_SCAN_STATUS.finished, severity: 5, update_time: new Date(), components: { total: 124, - summary: [{ - severity: 1, - count: 90 - }, { - severity: 3, - count: 10 - }, { - severity: 4, - count: 10 - }, { - severity: 5, - count: 13 - }] + summary: [ + { + severity: 1, + count: 90 + }, + { + severity: 3, + count: 10 + }, + { + severity: 4, + count: 10 + }, + { + severity: 5, + count: 13 + } + ] } }; let mockTag: Tag = { - "digest": "sha256:e5c82328a509aeb7c18c1d7fb36633dc638fcf433f651bdcda59c1cc04d3ee55", - "name": "nginx", - "size": "2049", - "architecture": "amd64", - "os": "linux", - "docker_version": "1.12.3", - "author": "steven", - "created": new Date("2016-11-08T22:41:15.912313785Z"), - "signature": null, - "scan_overview": mockVulnerability, - "labels": [], + digest: + "sha256:e5c82328a509aeb7c18c1d7fb36633dc638fcf433f651bdcda59c1cc04d3ee55", + name: "nginx", + size: "2049", + architecture: "amd64", + os: "linux", + docker_version: "1.12.3", + author: "steven", + created: new Date("2016-11-08T22:41:15.912313785Z"), + signature: null, + scan_overview: mockVulnerability, + labels: [] }; let config: IServiceConfig = { - repositoryBaseEndpoint: '/api/repositories/testing' + repositoryBaseEndpoint: "/api/repositories/testing" + }; + + let mockManifest: Manifest = { + manifset: {}, + // tslint:disable-next-line:max-line-length + config: `{"architecture":"amd64","config":{"Hostname":"","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd":["/bin/sh"],"ArgsEscaped":true,"Image":"sha256:fbef17698ac8605733924d5662f0cbfc0b27a51e83ab7d7a4b8d8a9a9fe0d1c2","Volumes":null,"WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":null},"container":"30e1a2427aa2325727a092488d304505780501585a6ccf5a6a53c4d83a826101","container_config":{"Hostname":"30e1a2427aa2","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd":["/bin/sh","-c","#(nop) ","CMD [\\"/bin/sh\\"]"],"ArgsEscaped":true,"Image":"sha256:fbef17698ac8605733924d5662f0cbfc0b27a51e83ab7d7a4b8d8a9a9fe0d1c2","Volumes":null,"WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":{}},"created":"2018-01-09T21:10:58.579708634Z","docker_version":"17.06.2-ce","history":[{"created":"2018-01-09T21:10:58.365737589Z","created_by":"/bin/sh -c #(nop) ADD file:093f0723fa46f6cdbd6f7bd146448bb70ecce54254c35701feeceb956414622f in / "},{"created":"2018-01-09T21:10:58.579708634Z","created_by":"/bin/sh -c #(nop) CMD [\\"/bin/sh\\"]","empty_layer":true}],"os":"linux","rootfs":{"type":"layers","diff_ids":["sha256:cd7100a72410606589a54b932cabd804a17f9ae5b42a1882bd56d263e02b6215"]}}` }; beforeEach(async(() => { TestBed.configureTestingModule({ - imports: [ - SharedModule - ], + imports: [SharedModule], declarations: [ TagDetailComponent, + TagHistoryComponent, ResultGridComponent, VULNERABILITY_DIRECTIVES, - LabelPieceComponent, - JobLogViewerComponent, + LabelPieceComponent, + JobLogViewerComponent, FilterComponent ], providers: [ ErrorHandler, ChannelService, JobLogDefaultService, - {provide: JobLogService, useClass: JobLogDefaultService}, + { provide: JobLogService, useClass: JobLogDefaultService }, { provide: SERVICE_CONFIG, useValue: config }, { provide: TagService, useClass: TagDefaultService }, - { provide: ScanningResultService, useClass: ScanningResultDefaultService } + { + provide: ScanningResultService, + useClass: ScanningResultDefaultService + } ] }); })); @@ -96,54 +125,83 @@ describe('TagDetailComponent (inline template)', () => { comp.repositoryId = "mock_repo"; tagService = fixture.debugElement.injector.get(TagService); - spy = spyOn(tagService, 'getTag').and.returnValues(Promise.resolve(mockTag)); + spy = spyOn(tagService, "getTag").and.returnValues( + Promise.resolve(mockTag) + ); let mockData: VulnerabilityItem[] = []; for (let i = 0; i < 30; i++) { let res: VulnerabilityItem = { id: "CVE-2016-" + (8859 + i), - severity: i % 2 === 0 ? VulnerabilitySeverity.HIGH : VulnerabilitySeverity.MEDIUM, + severity: + i % 2 === 0 + ? VulnerabilitySeverity.HIGH + : VulnerabilitySeverity.MEDIUM, package: "package_" + i, link: "https://security-tracker.debian.org/tracker/CVE-2016-4484", layer: "layer_" + i, - version: '4.' + i + ".0", - fixedVersion: '4.' + i + '.11', + version: "4." + i + ".0", + fixedVersion: "4." + i + ".11", description: "Mock data" }; mockData.push(res); } scanningService = fixture.debugElement.injector.get(ScanningResultService); - vulSpy = spyOn(scanningService, 'getVulnerabilityScanningResults').and.returnValue(Promise.resolve(mockData)); + vulSpy = spyOn( + scanningService, + "getVulnerabilityScanningResults" + ).and.returnValue(Promise.resolve(mockData)); + manifestSpy = spyOn(tagService, "getManifest").and.returnValues( + Promise.resolve(mockManifest) + ); fixture.detectChanges(); }); - it('should load data', async(() => { + it("should load data", async(() => { expect(spy.calls.any).toBeTruthy(); })); - it('should rightly display tag name and version', async(() => { + it("should load history data", async(() => { + expect(manifestSpy.calls.any).toBeTruthy(); + })); + + it("should rightly display tag name and version", async(() => { fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - let el: HTMLElement = fixture.nativeElement.querySelector('.custom-h2'); + let el: HTMLElement = fixture.nativeElement.querySelector(".custom-h2"); expect(el).toBeTruthy(); - expect(el.textContent.trim()).toEqual('mock_repo:nginx'); + expect(el.textContent.trim()).toEqual("mock_repo:nginx"); }); })); - it('should display tag details', async(() => { + it("should display tag details", async(() => { fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - let el: HTMLElement = fixture.nativeElement.querySelector('.image-detail-label .image-details'); + let el: HTMLElement = fixture.nativeElement.querySelector( + ".image-detail-label .image-details" + ); expect(el).toBeTruthy(); expect(el.textContent).toEqual("steven"); }); })); + it("should render history info", async(() => { + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + + let els: HTMLElement[] = fixture.nativeElement.querySelectorAll( + ".history-item" + ); + expect(els).toBeTruthy(); + expect(els.length).toBe(2); + }); + })); }); diff --git a/src/portal/lib/src/tag/tag-history.component.html b/src/portal/lib/src/tag/tag-history.component.html index 9d18fbf27..0b6cfff52 100644 --- a/src/portal/lib/src/tag/tag-history.component.html +++ b/src/portal/lib/src/tag/tag-history.component.html @@ -1,5 +1,5 @@ - {{ 'TAG.CREATION' | translate }} + {{ 'TAG.CREATION' | translate }} {{ 'TAG.COMMAND' | translate }} diff --git a/src/portal/lib/src/tag/tag-history.component.scss b/src/portal/lib/src/tag/tag-history.component.scss new file mode 100644 index 000000000..dc95e2e50 --- /dev/null +++ b/src/portal/lib/src/tag/tag-history.component.scss @@ -0,0 +1,3 @@ +.history-time { + width: 160px; +} \ No newline at end of file diff --git a/src/portal/lib/src/tag/tag-history.component.ts b/src/portal/lib/src/tag/tag-history.component.ts index 6e9f3da50..29196c716 100644 --- a/src/portal/lib/src/tag/tag-history.component.ts +++ b/src/portal/lib/src/tag/tag-history.component.ts @@ -6,6 +6,7 @@ import { ErrorHandler } from "../error-handler/index"; @Component({ selector: "hbr-tag-history", templateUrl: "./tag-history.component.html", + styleUrls: ["./tag-history.component.scss"], providers: [] }) diff --git a/src/portal/src/i18n/lang/en-us-lang.json b/src/portal/src/i18n/lang/en-us-lang.json index 919b7c78f..3fd523103 100644 --- a/src/portal/src/i18n/lang/en-us-lang.json +++ b/src/portal/src/i18n/lang/en-us-lang.json @@ -823,8 +823,8 @@ "UNKNOWN": "n/a", "STATUS": "Status", "START_TIME": "Start Time", - "END_TIME": "End Time", - "DETAILS": "Details", + "UPDATE_TIME": "Update Time", + "LOGS": "Logs", "PENDING": "Pending", "FINISHED": "Finished", "STOPPED": "Stopped", @@ -834,16 +834,17 @@ "NONE": "None", "DAILY": "Daily", "WEEKLY": "Weekly", - "MANUAL": "Manual" + "MANUAL": "Manual", + "ON": "on", + "AT": "at" }, "GC": { "CURRENT_SCHEDULE": "Current Schedule", "GC_NOW": "GC NOW", - "JOB_LIST": "GC Jobs List", + "JOB_HISTORY": "GC Jobs History", "JOB_ID": "Job ID", "TRIGGER_TYPE": "Trigger Type", "LATEST_JOBS": "Latest {{param}} Jobs", - "LOG_DETAIL": "Log Details", "MSG_SUCCESS": "Garbage Collection Successful", "MSG_SCHEDULE_SET": "Garbage Collection schedule has been set", "MSG_SCHEDULE_RESET": "Garbage Collection schedule has been reset" diff --git a/src/portal/src/i18n/lang/es-es-lang.json b/src/portal/src/i18n/lang/es-es-lang.json index 13122e322..1d3796d4c 100644 --- a/src/portal/src/i18n/lang/es-es-lang.json +++ b/src/portal/src/i18n/lang/es-es-lang.json @@ -821,8 +821,8 @@ "UNKNOWN": "n/a", "STATUS": "Status", "START_TIME": "Start Time", - "END_TIME": "End Time", - "DETAILS": "Details", + "UPDATE_TIME": "Update Time", + "LOGS": "Logs", "PENDING": "Pending", "FINISHED": "Finished", "STOPPED": "Stopped", @@ -832,16 +832,17 @@ "NONE": "None", "DAILY": "Daily", "WEEKLY": "Weekly", - "MANUAL": "Manual" + "MANUAL": "Manual", + "ON": "on", + "AT": "at" }, "GC": { "CURRENT_SCHEDULE": "Current Schedule", "GC_NOW": "GC NOW", - "JOB_LIST": "GC Jobs List", + "JOB_HISTORY": "GC Jobs History", "JOB_ID": "Job ID", "TRIGGER_TYPE": "Trigger Type", "LATEST_JOBS": "Latest {{param}} Jobs", - "LOG_DETAIL": "Log Details", "MSG_SUCCESS": "Garbage Collection Successful", "MSG_SCHEDULE_SET": "Garbage Collection schedule has been set", "MSG_SCHEDULE_RESET": "Garbage Collection schedule has been reset" diff --git a/src/portal/src/i18n/lang/fr-fr-lang.json b/src/portal/src/i18n/lang/fr-fr-lang.json index 89b146127..3fc53b93d 100644 --- a/src/portal/src/i18n/lang/fr-fr-lang.json +++ b/src/portal/src/i18n/lang/fr-fr-lang.json @@ -784,8 +784,8 @@ "UNKNOWN": "n. d.", "STATUS": "Status", "START_TIME": "Start Time", - "END_TIME": "End Time", - "DETAILS": "Details", + "UPDATE_TIME": "Update Time", + "LOGS": "Logs", "PENDING": "Pending", "FINISHED": "Finished", "STOPPED": "Stopped", @@ -795,16 +795,17 @@ "NONE": "None", "DAILY": "Daily", "WEEKLY": "Weekly", - "MANUAL": "Manual" + "MANUAL": "Manual", + "ON": "on", + "AT": "at" }, "GC": { "CURRENT_SCHEDULE": "Current Schedule", "GC_NOW": "GC NOW", - "JOB_LIST": "GC Jobs List", + "JOB_HISTORY": "GC Jobs History", "JOB_ID": "Job ID", "TRIGGER_TYPE": "Trigger Type", "LATEST_JOBS": "Latest {{param}} Jobs", - "LOG_DETAIL": "Log Details", "MSG_SUCCESS": "Garbage Collection Successful", "MSG_SCHEDULE_SET": "Garbage Collection schedule has been set", "MSG_SCHEDULE_RESET": "Garbage Collection schedule has been reset" diff --git a/src/portal/src/i18n/lang/zh-cn-lang.json b/src/portal/src/i18n/lang/zh-cn-lang.json index 93efb98b2..81cd91a57 100644 --- a/src/portal/src/i18n/lang/zh-cn-lang.json +++ b/src/portal/src/i18n/lang/zh-cn-lang.json @@ -818,9 +818,9 @@ "INCONRRECT_OLD_PWD": "旧密码不正确。", "UNKNOWN": "未知", "STATUS": "状态", - "START_TIME": "开始时间", - "END_TIME": "结束时间", - "DETAILS": "详情", + "START_TIME": "创建时间", + "UPDATE_TIME": "更新时间", + "LOGS": "日志", "PENDING": "未开始", "FINISHED": "已完成", "STOPPED": "已停止", @@ -830,16 +830,17 @@ "NONE": "无", "DAILY": "每天", "WEEKLY": "每周", - "MANUAL": "手动" + "MANUAL": "手动", + "ON": " ", + "AT": " " }, "GC": { "CURRENT_SCHEDULE": "当前定时任务", "GC_NOW": "立即清理垃圾", - "JOB_LIST": "任务列表", + "JOB_HISTORY": "历史任务", "JOB_ID": "任务ID", "TRIGGER_TYPE": "触发类型", "LATEST_JOBS": "最新的 {{param}} 个任务", - "LOG_DETAIL": "日志详情", "MSG_SUCCESS": "垃圾回收成功", "MSG_SCHEDULE_SET": "垃圾回收定时任务设置成功", "MSG_SCHEDULE_RESET": "垃圾回收定时任务已被重置"