Merge pull request #11834 from AllForNothing/release-2.0.0

[Cherry-pick]Improve i18n service
This commit is contained in:
Will Sun 2020-05-07 11:45:42 +08:00 committed by GitHub
commit d248a7b132
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 59 additions and 64 deletions

View File

@ -25,6 +25,7 @@ COPY src/portal /build_dir
ENV NPM_CONFIG_REGISTRY=${npm_registry} ENV NPM_CONFIG_REGISTRY=${npm_registry}
RUN npm install --unsafe-perm RUN npm install --unsafe-perm
RUN npm run generate-build-timestamp
RUN node --max_old_space_size=2048 'node_modules/@angular/cli/bin/ng' build --prod RUN node --max_old_space_size=2048 'node_modules/@angular/cli/bin/ng' build --prod
FROM ${harbor_base_namespace}/harbor-portal-base:${harbor_base_image_version} FROM ${harbor_base_namespace}/harbor-portal-base:${harbor_base_image_version}

View File

@ -19,7 +19,8 @@
"build": "ng build --aot", "build": "ng build --aot",
"release": "ng build --prod", "release": "ng build --prod",
"build-mock-api-server": "tsc -p server", "build-mock-api-server": "tsc -p server",
"mock-api-server": "npm run build-mock-api-server && node server/dist/server/src/mock-api.js" "mock-api-server": "npm run build-mock-api-server && node server/dist/server/src/mock-api.js",
"generate-build-timestamp": "node scripts/generate-build-timestamp.js"
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {

View File

@ -0,0 +1,19 @@
/**
* generate timestamp for each production build
*/
const fs = require('fs');
const data = fs.readFileSync('src/environments/environment.prod.ts', 'utf8').split('\n');
let buildTimestampIndex = 0;
data.forEach((item,index) => {
if(item.indexOf('buildTimestamp') !== -1) {
buildTimestampIndex = index;
}
});
if (buildTimestampIndex > 0) {
const timestamp = new Date().getTime();
data[buildTimestampIndex] = ` buildTimestamp: ${timestamp},`;
fs.writeFileSync('src/environments/environment.prod.ts', data.join('\n'), 'utf8');
}

View File

@ -81,19 +81,15 @@
</clr-vertical-nav-group> </clr-vertical-nav-group>
</div> </div>
<div> <div>
<div class="vertical-nav-footer"> <ng-container *ngFor="let theme of themeArray;let i=index">
<ng-container *ngFor="let theme of themeArray;let i=index"> <ng-container *ngIf="theme.showStyle === styleMode">
<ng-container *ngIf="theme.showStyle === styleMode"> <a clrVerticalNavLink (click)="themeChanged(theme)">
<a class="nav-link nav-icon theme-select" <clr-icon clrVerticalNavIcon size="20" *ngIf="styleMode ==='DARK'" shape="sun" class="is-solid"></clr-icon>
(click)="themeChanged(theme)"> <clr-icon clrVerticalNavIcon size="20" *ngIf="styleMode ==='LIGHT'" shape="moon" class="is-solid"></clr-icon>
<clr-icon size="20" *ngIf="styleMode ==='DARK'" shape="sun" class="is-solid"></clr-icon>
<clr-icon size="20" *ngIf="styleMode ==='LIGHT'" shape="moon" class="is-solid"></clr-icon>
{{ theme.text | translate }} {{ theme.text | translate }}
</a> </a>
</ng-container> </ng-container>
</ng-container> </ng-container>
</div>
<clr-vertical-nav-group routerLinkActive="active"> <clr-vertical-nav-group routerLinkActive="active">
<clr-icon shape="network-globe" clrVerticalNavIcon></clr-icon> <clr-icon shape="network-globe" clrVerticalNavIcon></clr-icon>
{{'SIDE_NAV.API_EXPLORER' | translate}} {{'SIDE_NAV.API_EXPLORER' | translate}}

View File

@ -32,22 +32,6 @@ clr-vertical-nav {
justify-content: space-between; justify-content: space-between;
} }
} }
.vertical-nav-footer {
margin: 5px 23px;
a {
display: inline-block;
line-height: 0;
padding: 0;
height: 24px;
&:hover {
background: transparent;
cursor: default;
}
.api-button {
margin: 0;
}
}
}
} }
.font-size-13 { .font-size-13 {
font-size: 13px; font-size: 13px;
@ -82,23 +66,3 @@ clr-vertical-nav {
.right { .right {
text-align: right; text-align: right;
} }
.theme-select {
width: 5.4rem;
display: flex;
align-items: center;
justify-content: flex-start;
height: 100%;
font-size: 14px;
letter-spacing: 1px;
cursor: pointer;
&:hover {
opacity: 1;
}
clr-icon {
position: static;
transform: none;
margin-right: .2rem;
min-width: 20px;
}
}

View File

@ -29,7 +29,12 @@
<clr-dg-column [clrDgField]="'version'">{{'VULNERABILITY.GRID.COLUMN_VERSION' | translate}}</clr-dg-column> <clr-dg-column [clrDgField]="'version'">{{'VULNERABILITY.GRID.COLUMN_VERSION' | translate}}</clr-dg-column>
<clr-dg-column [clrDgField]="'fix_version'">{{'VULNERABILITY.GRID.COLUMN_FIXED' | translate}}</clr-dg-column> <clr-dg-column [clrDgField]="'fix_version'">{{'VULNERABILITY.GRID.COLUMN_FIXED' | translate}}</clr-dg-column>
<clr-dg-placeholder>{{'VULNERABILITY.CHART.TOOLTIPS_TITLE_ZERO' | translate}}</clr-dg-placeholder> <clr-dg-placeholder>
<span *ngIf="hasScanned();else elseBlock">{{'VULNERABILITY.STATE.OTHER_STATUS' | translate}}</span>
<ng-template #elseBlock>
{{'VULNERABILITY.CHART.TOOLTIPS_TITLE_ZERO' | translate}}
</ng-template>
</clr-dg-placeholder>
<clr-dg-row *clrDgItems="let res of scanningResults"> <clr-dg-row *clrDgItems="let res of scanningResults">
<clr-dg-cell> <clr-dg-cell>
<span *ngIf="!res.links || res.links.length === 0">{{res.id}}</span> <span *ngIf="!res.links || res.links.length === 0">{{res.id}}</span>
@ -73,4 +78,4 @@
</clr-dg-footer> </clr-dg-footer>
</clr-datagrid> </clr-datagrid>
</div> </div>
</div> </div>

View File

@ -181,6 +181,13 @@ export class ArtifactVulnerabilitiesComponent implements OnInit, OnDestroy {
return this.hasViewInitWithDelay && this.resultBarChartComponent return this.hasViewInitWithDelay && this.resultBarChartComponent
&& (this.resultBarChartComponent.queued || this.resultBarChartComponent.scanning || this.resultBarChartComponent.error); && (this.resultBarChartComponent.queued || this.resultBarChartComponent.scanning || this.resultBarChartComponent.error);
} }
hasScanned(): boolean {
return this.hasViewInitWithDelay && this.resultBarChartComponent
&& !(this.resultBarChartComponent.completed
|| this.resultBarChartComponent.error
|| this.resultBarChartComponent.queued
|| this.resultBarChartComponent.scanning);
}
handleScanOverview(scanOverview: any): any { handleScanOverview(scanOverview: any): any {
if (scanOverview) { if (scanOverview) {
return scanOverview[DEFAULT_SUPPORTED_MIME_TYPE]; return scanOverview[DEFAULT_SUPPORTED_MIME_TYPE];

View File

@ -12,5 +12,6 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
export const environment = { export const environment = {
production: true production: true,
buildTimestamp: 0,
}; };

View File

@ -17,5 +17,6 @@
// The list of which env maps to which file can be found in `angular-cli.json`. // The list of which env maps to which file can be found in `angular-cli.json`.
export const environment = { export const environment = {
production: false production: false,
buildTimestamp: 0,
}; };

View File

@ -997,7 +997,7 @@
"SCANNING_PERCENT_EXPLAIN": "Scan completed percentage is calculated as # of successfully scanned images / total number of images referenced within the image index.", "SCANNING_PERCENT_EXPLAIN": "Scan completed percentage is calculated as # of successfully scanned images / total number of images referenced within the image index.",
"TOOLTIPS_TITLE": "{{totalVulnerability}} of {{totalPackages}} {{package}} have known {{vulnerability}}.", "TOOLTIPS_TITLE": "{{totalVulnerability}} of {{totalPackages}} {{package}} have known {{vulnerability}}.",
"TOOLTIPS_TITLE_SINGULAR": "{{totalVulnerability}} of {{totalPackages}} {{package}} has known {{vulnerability}}.", "TOOLTIPS_TITLE_SINGULAR": "{{totalVulnerability}} of {{totalPackages}} {{package}} has known {{vulnerability}}.",
"TOOLTIPS_TITLE_ZERO": "No recognizable vulnerability found" "TOOLTIPS_TITLE_ZERO": "No recognizable vulnerability detected"
}, },
"SEVERITY": { "SEVERITY": {
"CRITICAL": "Critical", "CRITICAL": "Critical",

View File

@ -997,7 +997,7 @@
"SCANNING_PERCENT_EXPLAIN": "Scan completed percentage is calculated as # of successfully scanned images / total number of images referenced within the image index.", "SCANNING_PERCENT_EXPLAIN": "Scan completed percentage is calculated as # of successfully scanned images / total number of images referenced within the image index.",
"TOOLTIPS_TITLE": "{{totalVulnerability}} of {{totalPackages}} {{package}} have known {{vulnerability}}.", "TOOLTIPS_TITLE": "{{totalVulnerability}} of {{totalPackages}} {{package}} have known {{vulnerability}}.",
"TOOLTIPS_TITLE_SINGULAR": "{{totalVulnerability}} of {{totalPackages}} {{package}} has known {{vulnerability}}.", "TOOLTIPS_TITLE_SINGULAR": "{{totalVulnerability}} of {{totalPackages}} {{package}} has known {{vulnerability}}.",
"TOOLTIPS_TITLE_ZERO": "No recognizable vulnerability found" "TOOLTIPS_TITLE_ZERO": "No recognizable vulnerability detected"
}, },
"SEVERITY": { "SEVERITY": {
"CRITICAL": "Critical", "CRITICAL": "Critical",

View File

@ -970,7 +970,7 @@
"SCANNING_PERCENT_EXPLAIN": "Scan completed percentage is calculated as # of successfully scanned images / total number of images referenced within the image index.", "SCANNING_PERCENT_EXPLAIN": "Scan completed percentage is calculated as # of successfully scanned images / total number of images referenced within the image index.",
"TOOLTIPS_TITLE": "{{totalVulnerability}} de {{totalPackages}} {{package}} ont des {{vulnerability}} connues.", "TOOLTIPS_TITLE": "{{totalVulnerability}} de {{totalPackages}} {{package}} ont des {{vulnerability}} connues.",
"TOOLTIPS_TITLE_SINGULAR": "{{totalVulnerability}} de {{totalPackages}} {{package}} a des {{vulnerability}} connues.", "TOOLTIPS_TITLE_SINGULAR": "{{totalVulnerability}} de {{totalPackages}} {{package}} a des {{vulnerability}} connues.",
"TOOLTIPS_TITLE_ZERO": "No recognizable vulnerability found" "TOOLTIPS_TITLE_ZERO": "No recognizable vulnerability detected"
}, },
"SEVERITY": { "SEVERITY": {
"CRITICAL": "Critique", "CRITICAL": "Critique",

View File

@ -993,7 +993,7 @@
"SCANNING_PERCENT_EXPLAIN": "Scan completed percentage is calculated as # of successfully scanned images / total number of images referenced within the image index.", "SCANNING_PERCENT_EXPLAIN": "Scan completed percentage is calculated as # of successfully scanned images / total number of images referenced within the image index.",
"TOOLTIPS_TITLE": "{{totalVulnerability}} de {{totalPackages}} {{package}} possuem {{vulnerability}}.", "TOOLTIPS_TITLE": "{{totalVulnerability}} de {{totalPackages}} {{package}} possuem {{vulnerability}}.",
"TOOLTIPS_TITLE_SINGULAR": "{{totalVulnerability}} de {{totalPackages}} {{package}} possuem {{vulnerability}}.", "TOOLTIPS_TITLE_SINGULAR": "{{totalVulnerability}} de {{totalPackages}} {{package}} possuem {{vulnerability}}.",
"TOOLTIPS_TITLE_ZERO": "No recognizable vulnerability found" "TOOLTIPS_TITLE_ZERO": "No recognizable vulnerability detected"
}, },
"SEVERITY": { "SEVERITY": {
"CRITICAL": "Crítico", "CRITICAL": "Crítico",

View File

@ -997,7 +997,7 @@
"SCANNING_PERCENT_EXPLAIN": "Scan completed percentage is calculated as # of successfully scanned images / total number of images referenced within the image index.", "SCANNING_PERCENT_EXPLAIN": "Scan completed percentage is calculated as # of successfully scanned images / total number of images referenced within the image index.",
"TOOLTIPS_TITLE": "{{totalVulnerability}} 'nın {{totalPackages}} {{package}} bilinen {{vulnerability}}.", "TOOLTIPS_TITLE": "{{totalVulnerability}} 'nın {{totalPackages}} {{package}} bilinen {{vulnerability}}.",
"TOOLTIPS_TITLE_SINGULAR": "{{totalVulnerability}} 'nın {{totalPackages}} {{package}} bilinen {{vulnerability}}.", "TOOLTIPS_TITLE_SINGULAR": "{{totalVulnerability}} 'nın {{totalPackages}} {{package}} bilinen {{vulnerability}}.",
"TOOLTIPS_TITLE_ZERO": "No recognizable vulnerability found" "TOOLTIPS_TITLE_ZERO": "No recognizable vulnerability detected"
}, },
"SEVERITY": { "SEVERITY": {
"CRITICAL": "Kritik", "CRITICAL": "Kritik",

View File

@ -997,7 +997,7 @@
"SCANNING_PERCENT_EXPLAIN": "扫描完成度是扫描成功的镜像数与总共需要扫描的镜像数的比值,总共需要的扫描的镜像不包含 Index 。", "SCANNING_PERCENT_EXPLAIN": "扫描完成度是扫描成功的镜像数与总共需要扫描的镜像数的比值,总共需要的扫描的镜像不包含 Index 。",
"TOOLTIPS_TITLE": "{{totalPackages}}个{{package}}中的{{totalVulnerability}}个含有{{vulnerability}}。", "TOOLTIPS_TITLE": "{{totalPackages}}个{{package}}中的{{totalVulnerability}}个含有{{vulnerability}}。",
"TOOLTIPS_TITLE_SINGULAR": "{{totalPackages}}个{{package}}中的{{totalVulnerability}}个含有{{vulnerability}}。", "TOOLTIPS_TITLE_SINGULAR": "{{totalPackages}}个{{package}}中的{{totalVulnerability}}个含有{{vulnerability}}。",
"TOOLTIPS_TITLE_ZERO": "没有发现可识别的漏洞" "TOOLTIPS_TITLE_ZERO": "没有检测到可识别的漏洞"
}, },
"SEVERITY": { "SEVERITY": {
"CRITICAL": "危急", "CRITICAL": "危急",

View File

@ -102,10 +102,6 @@ h4 {
top: 8px; top: 8px;
} }
.is-solid {
cursor: pointer;
}
.selectBox { .selectBox {
position: absolute; position: absolute;
width: 100%; width: 100%;
@ -296,4 +292,4 @@ clr-modal {
padding: 0; padding: 0;
} }
} }
} }

View File

@ -11,11 +11,15 @@ import { TranslateHttpLoader } from "@ngx-translate/http-loader";
import { MyMissingTranslationHandler } from "../../i18n/missing-trans.handler"; import { MyMissingTranslationHandler } from "../../i18n/missing-trans.handler";
import { TranslatorJsonLoader } from "../../i18n/local-json.loader"; import { TranslatorJsonLoader } from "../../i18n/local-json.loader";
import { ClipboardModule } from "../../components/third-party/ngx-clipboard"; import { ClipboardModule } from "../../components/third-party/ngx-clipboard";
import { environment } from '../../../environments/environment';
export function GeneralTranslatorLoader(http: HttpClient, config: IServiceConfig) { export function GeneralTranslatorLoader(http: HttpClient, config: IServiceConfig) {
if (config && config.langMessageLoader === 'http') { if (config && config.langMessageLoader === 'http') {
let prefix: string = config.langMessagePathForHttpLoader ? config.langMessagePathForHttpLoader : "i18n/lang/"; const prefix: string = config.langMessagePathForHttpLoader ? config.langMessagePathForHttpLoader : "i18n/lang/";
let suffix: string = config.langMessageFileSuffixForHttpLoader ? config.langMessageFileSuffixForHttpLoader : "-lang.json"; let suffix: string = config.langMessageFileSuffixForHttpLoader ? config.langMessageFileSuffixForHttpLoader : "-lang.json";
if (environment && environment.buildTimestamp) {
suffix += `?buildTimeStamp=${environment.buildTimestamp}`;
}
return new TranslateHttpLoader(http, prefix, suffix); return new TranslateHttpLoader(http, prefix, suffix);
} else { } else {
return new TranslatorJsonLoader(config); return new TranslatorJsonLoader(config);