mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-23 02:35:17 +01:00
Merge pull request #3338 from pengpengshui/master
fix issue about pull command in repository #3275
This commit is contained in:
commit
a5ca531819
@ -8,7 +8,8 @@
|
||||
"outDir": "dist",
|
||||
"assets": [
|
||||
"images",
|
||||
"favicon.ico"
|
||||
"favicon.ico",
|
||||
"setting.json"
|
||||
],
|
||||
"index": "index.html",
|
||||
"main": "main.ts",
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
||||
import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core';
|
||||
|
||||
import { COPY_INPUT_HTML } from './copy-input.html';
|
||||
import { PUSH_IMAGE_STYLE } from './push-image.css';
|
||||
@ -14,16 +14,19 @@ export const enum CopyStatus {
|
||||
|
||||
providers: []
|
||||
})
|
||||
export class CopyInputComponent {
|
||||
|
||||
export class CopyInputComponent implements OnInit {
|
||||
@Input() inputSize: number = 40;
|
||||
@Input() headerTitle: string = "Copy Input";
|
||||
@Input() defaultValue: string = "N/A";
|
||||
@Input() iconMode: boolean = false;
|
||||
|
||||
state: CopyStatus = CopyStatus.NORMAL;
|
||||
|
||||
@Output() onCopySuccess: EventEmitter<any> = new EventEmitter<any>();
|
||||
@Output() onCopyError: EventEmitter<any> = new EventEmitter<any>();
|
||||
|
||||
ngOnInit(): void { }
|
||||
onSuccess($event: any): void {
|
||||
this.state = CopyStatus.SUCCESS;
|
||||
this.onCopySuccess.emit($event);
|
||||
@ -38,6 +41,10 @@ export class CopyInputComponent {
|
||||
this.state = CopyStatus.NORMAL;
|
||||
}
|
||||
|
||||
setPullCommendShow(): void {
|
||||
this.iconMode = false;
|
||||
}
|
||||
|
||||
public get isCopied(): boolean {
|
||||
return this.state === CopyStatus.SUCCESS;
|
||||
}
|
||||
|
@ -1,15 +1,19 @@
|
||||
export const COPY_INPUT_HTML: string = `
|
||||
<div>
|
||||
<div class="command-title">
|
||||
<div class="command-title" *ngIf="!iconMode">
|
||||
{{headerTitle}}
|
||||
</div>
|
||||
<div>
|
||||
<span>
|
||||
<span [class.hide]="iconMode">
|
||||
<input type="text" class="command-input" size="{{inputSize}}" [(ngModel)]="defaultValue" #inputTarget readonly/>
|
||||
</span>
|
||||
<span>
|
||||
<clr-icon shape="copy" [class.is-success]="isCopied" [class.is-error]="hasCopyError" class="info-tips-icon" size="24" [ngxClipboard]="inputTarget" (cbOnSuccess)="onSuccess($event)" (cbOnError)="onError($event)"></clr-icon>
|
||||
<input type="text" size="{{inputSize}}" [(ngModel)]="defaultValue" #inputTarget1 style="width: 1px; min-width: 0px; padding: 0;">
|
||||
</span>
|
||||
<span>
|
||||
<clr-icon shape="copy" [class.is-success]="isCopied" [class.is-error]="hasCopyError" class="info-tips-icon" size="24" [ngxClipboard]="inputTarget1" (cbOnSuccess)="onSuccess($event)" (cbOnError)="onError($event)"></clr-icon>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
`;
|
@ -43,4 +43,7 @@ export const PUSH_IMAGE_STYLE: string = `
|
||||
.btn-font {
|
||||
font-size: 14px !important;
|
||||
}
|
||||
.hide{
|
||||
display:none;
|
||||
}
|
||||
`;
|
@ -15,12 +15,12 @@ export const TAG_TEMPLATE = `
|
||||
|
||||
<h2 *ngIf="!isEmbedded" class="sub-header-title">{{repoName}}</h2>
|
||||
<clr-datagrid [clrDgLoading]="loading" [class.embeded-datagrid]="isEmbedded">
|
||||
<clr-dg-column style="width: 80px;" [clrDgField]="'name'">{{'REPOSITORY.TAG' | translate}}</clr-dg-column>
|
||||
<clr-dg-column style="width: 80px;" [clrDgField]="'size'">{{'REPOSITORY.SIZE' | translate}}</clr-dg-column>
|
||||
<clr-dg-column style="min-width: 180px;">{{'REPOSITORY.PULL_COMMAND' | translate}}</clr-dg-column>
|
||||
<clr-dg-column style="width: 160px;" *ngIf="withClair">{{'VULNERABILITY.SINGULAR' | translate}}</clr-dg-column>
|
||||
<clr-dg-column style="min-width: 160px;" [clrDgField]="'name'">{{'REPOSITORY.TAG' | translate}}</clr-dg-column>
|
||||
<clr-dg-column style="width: 90px;" [clrDgField]="'size'">{{'REPOSITORY.SIZE' | translate}}</clr-dg-column>
|
||||
<clr-dg-column style="min-width: 120px; max-width:220px;">{{'REPOSITORY.PULL_COMMAND' | translate}}</clr-dg-column>
|
||||
<clr-dg-column style="width: 140px;" *ngIf="withClair">{{'VULNERABILITY.SINGULAR' | translate}}</clr-dg-column>
|
||||
<clr-dg-column style="width: 80px;" *ngIf="withNotary">{{'REPOSITORY.SIGNED' | translate}}</clr-dg-column>
|
||||
<clr-dg-column style="width: 100px;">{{'REPOSITORY.AUTHOR' | translate}}</clr-dg-column>
|
||||
<clr-dg-column style="width: 130px;">{{'REPOSITORY.AUTHOR' | translate}}</clr-dg-column>
|
||||
<clr-dg-column style="width: 160px;"[clrDgSortBy]="createdComparator">{{'REPOSITORY.CREATED' | translate}}</clr-dg-column>
|
||||
<clr-dg-column style="width: 80px;" [clrDgField]="'docker_version'" *ngIf="!withClair">{{'REPOSITORY.DOCKER_VERSION' | translate}}</clr-dg-column>
|
||||
<clr-dg-placeholder>{{'TGA.PLACEHOLDER' | translate }}</clr-dg-placeholder>
|
||||
@ -30,13 +30,15 @@ export const TAG_TEMPLATE = `
|
||||
<button class="action-item" *ngIf="hasProjectAdminRole" (click)="deleteTag(t)">{{'REPOSITORY.DELETE' | translate}}</button>
|
||||
<button class="action-item" (click)="showDigestId(t)">{{'REPOSITORY.COPY_DIGEST_ID' | translate}}</button>
|
||||
</clr-dg-action-overflow>
|
||||
<clr-dg-cell style="width: 80px;" [ngSwitch]="existObservablePackage(t)">
|
||||
<a *ngSwitchCase="true" href="javascript:void(0)" (click)="onTagClick(t)">{{t.name}}</a>
|
||||
<clr-dg-cell class="truncated" style="min-width: 160px;" [ngSwitch]="withClair">
|
||||
<a *ngSwitchCase="true" href="javascript:void(0)" (click)="onTagClick(t)" title="{{t.name}}">{{t.name}}</a>
|
||||
<span *ngSwitchDefault>{{t.name}}</span>
|
||||
</clr-dg-cell>
|
||||
<clr-dg-cell style="width: 80px;">{{t.size}}</clr-dg-cell>
|
||||
<clr-dg-cell style="min-width: 180px;" class="truncated" title="docker pull {{registryUrl}}/{{repoName}}:{{t.name}}">docker pull {{registryUrl}}/{{repoName}}:{{t.name}}</clr-dg-cell>
|
||||
<clr-dg-cell style="width: 160px;" *ngIf="withClair">
|
||||
<clr-dg-cell style="width: 90px;">{{t.size}}</clr-dg-cell>
|
||||
<clr-dg-cell style="min-width: 120px; max-width:220px;" class="truncated" title="docker pull {{registryUrl}}/{{repoName}}:{{t.name}}">
|
||||
<hbr-copy-input #copyInput (onCopyError)="onCpError($event)" iconMode="true" defaultValue="docker pull {{registryUrl}}/{{repoName}}:{{t.name}}"></hbr-copy-input>
|
||||
</clr-dg-cell>
|
||||
<clr-dg-cell style="width: 140px;" *ngIf="withClair">
|
||||
<hbr-vulnerability-bar [repoName]="repoName" [tagId]="t.name" [summary]="t.scan_overview"></hbr-vulnerability-bar>
|
||||
</clr-dg-cell>
|
||||
<clr-dg-cell style="width: 80px;" *ngIf="withNotary" [ngSwitch]="t.signature !== null">
|
||||
@ -47,7 +49,7 @@ export const TAG_TEMPLATE = `
|
||||
<span class="tooltip-content">{{'REPOSITORY.NOTARY_IS_UNDETERMINED' | translate}}</span>
|
||||
</a>
|
||||
</clr-dg-cell>
|
||||
<clr-dg-cell style="width: 100px;">{{t.author}}</clr-dg-cell>
|
||||
<clr-dg-cell class="truncated" style="width: 130px;" title="{{t.author}}">{{t.author}}</clr-dg-cell>
|
||||
<clr-dg-cell style="width: 160px;">{{t.created | date: 'short'}}</clr-dg-cell>
|
||||
<clr-dg-cell style="width: 80px;" *ngIf="!withClair">{{t.docker_version}}</clr-dg-cell>
|
||||
</clr-dg-row>
|
||||
|
@ -18,6 +18,7 @@ import { Observable, Subscription } from 'rxjs/Rx';
|
||||
import { ChannelService } from '../channel/index';
|
||||
|
||||
import { JobLogViewerComponent } from '../job-log-viewer/index';
|
||||
import {CopyInputComponent} from "../push-image/copy-input.component";
|
||||
|
||||
describe('TagComponent (inline template)', () => {
|
||||
|
||||
@ -53,7 +54,8 @@ describe('TagComponent (inline template)', () => {
|
||||
ConfirmationDialogComponent,
|
||||
VULNERABILITY_DIRECTIVES,
|
||||
FILTER_DIRECTIVES,
|
||||
JobLogViewerComponent
|
||||
JobLogViewerComponent,
|
||||
CopyInputComponent
|
||||
],
|
||||
providers: [
|
||||
ErrorHandler,
|
||||
|
@ -50,6 +50,7 @@ import {
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
import { State, Comparator } from 'clarity-angular';
|
||||
import {CopyInputComponent} from "../push-image/copy-input.component";
|
||||
|
||||
@Component({
|
||||
selector: 'hbr-tag',
|
||||
@ -91,6 +92,8 @@ export class TagComponent implements OnInit {
|
||||
confirmationDialog: ConfirmationDialogComponent;
|
||||
|
||||
@ViewChild('digestTarget') textInput: ElementRef;
|
||||
@ViewChild('copyInput') copyInput: CopyInputComponent;
|
||||
|
||||
|
||||
constructor(
|
||||
private errorHandler: ErrorHandler,
|
||||
@ -253,7 +256,7 @@ export class TagComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
//Get vulnerability scanning status
|
||||
//Get vulnerability scanning status
|
||||
scanStatus(t: Tag): string {
|
||||
if (t && t.scan_overview && t.scan_overview.scan_status) {
|
||||
return t.scan_overview.scan_status;
|
||||
@ -285,4 +288,9 @@ export class TagComponent implements OnInit {
|
||||
this.channel.publishScanEvent(this.repoName + "/" + tagId);
|
||||
}
|
||||
}
|
||||
|
||||
//pull command
|
||||
onCpError($event: any): void {
|
||||
this.copyInput.setPullCommendShow();
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@
|
||||
"clarity-icons": "^0.9.8",
|
||||
"clarity-ui": "^0.9.8",
|
||||
"core-js": "^2.4.1",
|
||||
"harbor-ui": "0.4.72",
|
||||
"harbor-ui": "0.4.83",
|
||||
"intl": "^1.2.5",
|
||||
"mutationobserver-shim": "^0.3.2",
|
||||
"ngx-cookie": "^1.0.0",
|
||||
|
@ -24,7 +24,7 @@
|
||||
flex-direction: column;
|
||||
height: auto;
|
||||
position: relative;
|
||||
margin-left: 1px;
|
||||
border-left: 1px solid #eee;
|
||||
}
|
||||
|
||||
.login-wrapper-override {
|
||||
|
@ -1,4 +1,4 @@
|
||||
<div class="login-wrapper login-wrapper-override">
|
||||
<div class="login-wrapper login-wrapper-override" [ngStyle]="{'background-image': 'url(' + customLoginBgImg + ')'}">
|
||||
<form #signInForm="ngForm" class="login">
|
||||
<label class="title">{{appTitle | translate}}<span class="trademark tm-font">™</span>
|
||||
</label>
|
||||
@ -12,7 +12,7 @@
|
||||
{{ 'TOOLTIP.SIGN_IN_USERNAME' | translate }}
|
||||
</span>
|
||||
</label>
|
||||
<label for="username" aria-haspopup="true" role="tooltip" class="tooltip tooltip-validation tooltip-md tooltip-top-left">
|
||||
<label for="username" aria-haspopup="true" role="tpopular-repo-wrapperooltip" class="tooltip tooltip-validation tooltip-md tooltip-top-left">
|
||||
<input class="password" type="password" required
|
||||
[(ngModel)]="signInCredential.password"
|
||||
name="login_password" id="login_password" placeholder='{{"PLACEHOLDER.SIGN_IN_PWD" | translate}}'
|
||||
|
@ -28,6 +28,7 @@ import { AppConfig } from '../../app-config';
|
||||
import { User } from '../../user/user';
|
||||
|
||||
import { CookieService, CookieOptions } from 'ngx-cookie';
|
||||
import {SkinableConfig} from "../../skinable-config.service";
|
||||
|
||||
//Define status flags for signing in states
|
||||
export const signInStatusNormal = 0;
|
||||
@ -48,6 +49,8 @@ export class SignInComponent implements AfterViewChecked, OnInit {
|
||||
//Remeber me indicator
|
||||
rememberMe: boolean = false;
|
||||
rememberedName: string = "";
|
||||
|
||||
customLoginBgImg: string;
|
||||
//Form reference
|
||||
signInForm: NgForm;
|
||||
@ViewChild('signInForm') currentForm: NgForm;
|
||||
@ -68,10 +71,16 @@ export class SignInComponent implements AfterViewChecked, OnInit {
|
||||
private session: SessionService,
|
||||
private route: ActivatedRoute,
|
||||
private appConfigService: AppConfigService,
|
||||
private cookie: CookieService
|
||||
) { }
|
||||
private cookie: CookieService,
|
||||
private skinableConfig: SkinableConfig) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
// custom skin
|
||||
let customSkinObj = this.skinableConfig.getSkinConfig();
|
||||
if (customSkinObj && customSkinObj.loginBgImg) {
|
||||
this.customLoginBgImg = customSkinObj.loginBgImg;
|
||||
}
|
||||
|
||||
//Make sure the updated configuration can be loaded
|
||||
this.appConfigService.load()
|
||||
.then(updatedConfig => this.appConfig = updatedConfig);
|
||||
|
@ -23,9 +23,13 @@ import { ConfigurationModule } from './config/config.module';
|
||||
|
||||
import { TranslateService } from "@ngx-translate/core";
|
||||
import { AppConfigService } from './app-config.service';
|
||||
import {SkinableConfig} from "./skinable-config.service";
|
||||
|
||||
export function initConfig(configService: AppConfigService) {
|
||||
return () => configService.load();
|
||||
export function initConfig(configService: AppConfigService, skinableService: SkinableConfig) {
|
||||
return () => {
|
||||
skinableService.getCustomFile();
|
||||
configService.load();
|
||||
}
|
||||
}
|
||||
|
||||
export function getCurrentLanguage(translateService: TranslateService) {
|
||||
@ -41,14 +45,15 @@ export function getCurrentLanguage(translateService: TranslateService) {
|
||||
BaseModule,
|
||||
AccountModule,
|
||||
HarborRoutingModule,
|
||||
ConfigurationModule
|
||||
ConfigurationModule,
|
||||
],
|
||||
providers: [
|
||||
AppConfigService,
|
||||
SkinableConfig,
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
useFactory: initConfig,
|
||||
deps: [ AppConfigService ],
|
||||
deps: [ AppConfigService, SkinableConfig],
|
||||
multi: true
|
||||
},
|
||||
{
|
||||
|
@ -23,6 +23,8 @@ import { AppConfigService } from '../../app-config.service';
|
||||
|
||||
import 'rxjs/add/operator/debounceTime';
|
||||
import 'rxjs/add/operator/distinctUntilChanged';
|
||||
import {TranslateService} from "@ngx-translate/core";
|
||||
import {SkinableConfig} from "../../skinable-config.service";
|
||||
|
||||
const deBounceTime = 500; //ms
|
||||
|
||||
@ -43,16 +45,31 @@ export class GlobalSearchComponent implements OnInit, OnDestroy {
|
||||
isResPanelOpened: boolean = false;
|
||||
searchTerm: string = "";
|
||||
|
||||
//Placeholder text
|
||||
placeholderText: string = "GLOBAL_SEARCH.PLACEHOLDER";
|
||||
placeholderText: string;
|
||||
|
||||
constructor(
|
||||
private searchTrigger: SearchTriggerService,
|
||||
private router: Router,
|
||||
private appConfigService: AppConfigService) { }
|
||||
private appConfigService: AppConfigService,
|
||||
private translate: TranslateService,
|
||||
private skinableConfig: SkinableConfig) {
|
||||
}
|
||||
|
||||
//Implement ngOnIni
|
||||
ngOnInit(): void {
|
||||
//custom skin
|
||||
let customSkinObj = this.skinableConfig.getProjects();
|
||||
if (customSkinObj && customSkinObj.projectName) {
|
||||
this.translate.get('GLOBAL_SEARCH.PLACEHOLDER', {'param': customSkinObj.projectName}).subscribe(res => {
|
||||
//Placeholder text
|
||||
this.placeholderText = res;
|
||||
});
|
||||
}else {
|
||||
this.translate.get('GLOBAL_SEARCH.PLACEHOLDER', {'param': 'Harbor'}).subscribe(res => {
|
||||
//Placeholder text
|
||||
this.placeholderText = res;
|
||||
});
|
||||
}
|
||||
|
||||
this.searchSub = this.searchTerms
|
||||
.debounceTime(deBounceTime)
|
||||
//.distinctUntilChanged()
|
||||
|
@ -1,8 +1,9 @@
|
||||
<clr-header class="header-5 header">
|
||||
<clr-header class="header-5 header" [ngStyle]='{"background-color": customStyle?.headerBgColor?customStyle?.headerBgColor:"#004a70" }'>
|
||||
<div class="branding">
|
||||
<a href="javascript:void(0)" class="nav-link" (click)="homeAction()">
|
||||
<clr-icon shape="vm-bug"></clr-icon>
|
||||
<span class="title">{{ appTitle | translate}}</span>
|
||||
<clr-icon shape="vm-bug" *ngIf="!customStyle?.headerLogo"></clr-icon>
|
||||
<img [attr.src]="customStyle?.headerLogo" *ngIf="customStyle?.headerLogo" style="width: 36px;height: 36px; object-fit: fill;">
|
||||
<span class="title">{{customProjectName?.projectName? customProjectName?.projectName:(appTitle | translate)}}</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="header-nav">
|
||||
|
@ -26,6 +26,7 @@ import { supportedLangs, enLang, languageNames, CommonRoutes } from '../../share
|
||||
import { AppConfigService } from '../../app-config.service';
|
||||
import { SearchTriggerService } from '../global-search/search-trigger.service';
|
||||
import { MessageHandlerService } from '../../shared/message-handler/message-handler.service';
|
||||
import {SkinableConfig} from "../../skinable-config.service";
|
||||
|
||||
@Component({
|
||||
selector: 'navigator',
|
||||
@ -40,6 +41,8 @@ export class NavigatorComponent implements OnInit {
|
||||
|
||||
selectedLang: string = enLang;
|
||||
appTitle: string = 'APP_TITLE.HARBOR';
|
||||
customStyle: {[key: string]: any};
|
||||
customProjectName: {[key: string]: any};
|
||||
|
||||
constructor(
|
||||
private session: SessionService,
|
||||
@ -48,11 +51,20 @@ export class NavigatorComponent implements OnInit {
|
||||
private cookie: CookieService,
|
||||
private appConfigService: AppConfigService,
|
||||
private msgHandler: MessageHandlerService,
|
||||
private searchTrigger: SearchTriggerService) {
|
||||
|
||||
private searchTrigger: SearchTriggerService,
|
||||
private skinableConfig: SkinableConfig) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
// custom skin
|
||||
let customSkinObj = this.skinableConfig.getSkinConfig();
|
||||
if (customSkinObj) {
|
||||
if (customSkinObj.projects) {
|
||||
this.customProjectName = customSkinObj.projects;
|
||||
}
|
||||
this.customStyle = customSkinObj;
|
||||
}
|
||||
|
||||
this.selectedLang = this.translate.currentLang;
|
||||
this.translate.onLangChange.subscribe((langChange: {lang: string}) => {
|
||||
this.selectedLang = langChange.lang;
|
||||
|
@ -1,15 +1,15 @@
|
||||
<clr-modal [(clrModalOpen)]="opened" [clrModalClosable]="false" [clrModalStaticBackdrop]="false">
|
||||
<h3 class="modal-title margin-left-override">vmware</h3>
|
||||
<h3 class="modal-title margin-left-override">{{customName?.companyName? customName?.companyName : 'vmware'}}</h3>
|
||||
<div class="modal-body margin-left-override">
|
||||
<div>
|
||||
<h2>Harbor</h2>
|
||||
<h2>{{customName?.projectName? customName?.projectName : ('APP_TITLE.HARBOR' | translate)}}</h2>
|
||||
</div>
|
||||
<div style="height: 12px;"></div>
|
||||
<div>
|
||||
<span class="p5 about-version">{{'ABOUT.VERSION' | translate}} {{version}}</span>
|
||||
</div>
|
||||
<div style="height: 12px;"></div>
|
||||
<div>
|
||||
<div *ngIf="!customIntroduction">
|
||||
<p class="p5">{{'ABOUT.COPYRIGHT' | translate}} <a href="http://www.vmware.com/go/patents" target="_blank" class="about-text-link">http://www.vmware.com/go/patents</a> {{'ABOUT.COPYRIGHT_SUFIX' | translate}}</p>
|
||||
<p class="p5">{{'ABOUT.TRADEMARK' | translate}}</p>
|
||||
<p class="p5">
|
||||
@ -17,6 +17,9 @@
|
||||
</p>
|
||||
<div style="height: 24px;"></div>
|
||||
</div>
|
||||
<div *ngIf="customIntroduction">
|
||||
<p class="p5">{{customIntroduction}}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer margin-left-override">
|
||||
<button type="button" class="btn btn-primary" (click)="close()">{{'BUTTON.CLOSE' | translate}}</button>
|
||||
|
@ -11,20 +11,39 @@
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
import { Component } from '@angular/core';
|
||||
import {Component, OnInit} from '@angular/core';
|
||||
|
||||
import { AppConfigService } from '../../app-config.service';
|
||||
import {TranslateService} from "@ngx-translate/core";
|
||||
import {SkinableConfig} from "../../skinable-config.service";
|
||||
|
||||
@Component({
|
||||
selector: 'about-dialog',
|
||||
templateUrl: "about-dialog.component.html",
|
||||
styleUrls: ["about-dialog.component.css"]
|
||||
})
|
||||
export class AboutDialogComponent {
|
||||
export class AboutDialogComponent implements OnInit{
|
||||
opened: boolean = false;
|
||||
build: string = "4276418";
|
||||
customIntroduction: string;
|
||||
customName: {[key: string]: any };
|
||||
|
||||
constructor(private appConfigService: AppConfigService) { }
|
||||
constructor(private appConfigService: AppConfigService,
|
||||
private translate: TranslateService,
|
||||
private skinableConfig: SkinableConfig) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
// custom skin
|
||||
let customSkinObj = this.skinableConfig.getProjects();
|
||||
if (customSkinObj) {
|
||||
let selectedLang = this.translate.currentLang;
|
||||
this.customName = customSkinObj;
|
||||
if (customSkinObj.introduction && customSkinObj.introduction[selectedLang]) {
|
||||
this.customIntroduction = customSkinObj.introduction[selectedLang];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public get version(): string {
|
||||
let appConfig = this.appConfigService.getConfig();
|
||||
|
34
src/ui_ng/src/app/skinable-config.service.ts
Normal file
34
src/ui_ng/src/app/skinable-config.service.ts
Normal file
@ -0,0 +1,34 @@
|
||||
|
||||
import {Injectable} from "@angular/core";
|
||||
import {Http} from "@angular/http";
|
||||
import {Observable} from "rxjs/Observable";
|
||||
/**
|
||||
* Created by pengf on 9/15/2017.
|
||||
*/
|
||||
|
||||
@Injectable()
|
||||
export class SkinableConfig {
|
||||
customSkinData: {[key: string]: any};
|
||||
constructor(private http: Http) {}
|
||||
|
||||
public getCustomFile(): Promise<any> {
|
||||
return this.http.get('../setting.json')
|
||||
.toPromise()
|
||||
.then(response => { this.customSkinData = response.json(); return this.customSkinData; })
|
||||
.catch(error => {
|
||||
console.error('custom skin json file load failed');
|
||||
});
|
||||
}
|
||||
|
||||
public getSkinConfig() {
|
||||
return this.customSkinData;
|
||||
}
|
||||
|
||||
public getProjects() {
|
||||
if (this.customSkinData) {
|
||||
return this.customSkinData.projects;
|
||||
}else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -86,7 +86,7 @@
|
||||
"LOGOUT": "Log Out"
|
||||
},
|
||||
"GLOBAL_SEARCH": {
|
||||
"PLACEHOLDER": "Search Harbor...",
|
||||
"PLACEHOLDER": "Search {{param}}...",
|
||||
"PLACEHOLDER_VIC": "Search Registry..."
|
||||
},
|
||||
"SIDE_NAV": {
|
||||
|
@ -86,7 +86,7 @@
|
||||
"LOGOUT": "Cerrar sesión"
|
||||
},
|
||||
"GLOBAL_SEARCH": {
|
||||
"PLACEHOLDER": "Buscar en Harbor...",
|
||||
"PLACEHOLDER": "Buscar en {{param}}...",
|
||||
"PLACEHOLDER_VIC": "Buscar en el registro..."
|
||||
},
|
||||
"SIDE_NAV": {
|
||||
|
@ -86,7 +86,7 @@
|
||||
"LOGOUT": "退出"
|
||||
},
|
||||
"GLOBAL_SEARCH": {
|
||||
"PLACEHOLDER": "搜索 Harbor...",
|
||||
"PLACEHOLDER": "搜索 {{param}}...",
|
||||
"PLACEHOLDER_VIC": "搜索 Registry..."
|
||||
},
|
||||
"SIDE_NAV": {
|
||||
|
Loading…
Reference in New Issue
Block a user