add customSkin about #3241

This commit is contained in:
Fuhui Peng (c) 2017-10-16 10:54:38 +08:00
parent eacb8e5658
commit a5a62e1b19
14 changed files with 129 additions and 28 deletions

View File

@ -8,7 +8,8 @@
"outDir": "dist",
"assets": [
"images",
"favicon.ico"
"favicon.ico",
"setting.json"
],
"index": "index.html",
"main": "main.ts",

View File

@ -24,7 +24,7 @@
flex-direction: column;
height: auto;
position: relative;
margin-left: 1px;
border-left: 1px solid #eee;
}
.login-wrapper-override {

View File

@ -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">&#8482;</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}}'

View File

@ -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);

View File

@ -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
},
{

View File

@ -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()

View File

@ -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">

View File

@ -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;

View File

@ -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>

View File

@ -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();

View 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;
}
}
}

View File

@ -86,7 +86,7 @@
"LOGOUT": "Log Out"
},
"GLOBAL_SEARCH": {
"PLACEHOLDER": "Search Harbor...",
"PLACEHOLDER": "Search {{param}}...",
"PLACEHOLDER_VIC": "Search Registry..."
},
"SIDE_NAV": {

View File

@ -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": {

View File

@ -86,7 +86,7 @@
"LOGOUT": "退出"
},
"GLOBAL_SEARCH": {
"PLACEHOLDER": "搜索 Harbor...",
"PLACEHOLDER": "搜索 {{param}}...",
"PLACEHOLDER_VIC": "搜索 Registry..."
},
"SIDE_NAV": {