|
|
@ -84,11 +84,10 @@ export class AppComponent {
|
|
|
|
Run the following command in `angular` folder to create a new component called `LogoComponent`.
|
|
|
|
Run the following command in `angular` folder to create a new component called `LogoComponent`.
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
```bash
|
|
|
|
yarn ng generate component logo --inlineTemplate --inlineStyle --entryComponent
|
|
|
|
yarn ng generate component logo --inlineTemplate --inlineStyle
|
|
|
|
|
|
|
|
|
|
|
|
# You don't need the --entryComponent option in Angular 9
|
|
|
|
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Open the generated `logo.component.ts` in `src/app/logo` folder and replace its content with the following:
|
|
|
|
Open the generated `logo.component.ts` in `src/app/logo` folder and replace its content with the following:
|
|
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
```js
|
|
|
@ -115,7 +114,7 @@ Open `app.component.ts` in `src/app` folder and modify it as shown below:
|
|
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
```js
|
|
|
|
import { ..., ReplaceableComponentsService } from '@abp/ng.core'; // imported ReplaceableComponentsService
|
|
|
|
import { ..., ReplaceableComponentsService } from '@abp/ng.core'; // imported ReplaceableComponentsService
|
|
|
|
import { LogoComponent } from './logo/logo.component'; // imported NavItemsComponent
|
|
|
|
import { LogoComponent } from './logo/logo.component'; // imported LogoComponent
|
|
|
|
import { eThemeBasicComponents } from '@abp/ng.theme.basic'; // imported eThemeBasicComponents
|
|
|
|
import { eThemeBasicComponents } from '@abp/ng.theme.basic'; // imported eThemeBasicComponents
|
|
|
|
//...
|
|
|
|
//...
|
|
|
|
|
|
|
|
|
|
|
@ -151,36 +150,18 @@ yarn ng generate component routes
|
|
|
|
Open the generated `routes.component.ts` in `src/app/routes` folder and replace its content with the following:
|
|
|
|
Open the generated `routes.component.ts` in `src/app/routes` folder and replace its content with the following:
|
|
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
```js
|
|
|
|
import { ABP } from '@abp/ng.core';
|
|
|
|
import { Component, HostBinding } from '@angular/core';
|
|
|
|
import {
|
|
|
|
|
|
|
|
Component,
|
|
|
|
|
|
|
|
HostBinding,
|
|
|
|
|
|
|
|
Inject,
|
|
|
|
|
|
|
|
Renderer2,
|
|
|
|
|
|
|
|
TrackByFunction,
|
|
|
|
|
|
|
|
AfterViewInit,
|
|
|
|
|
|
|
|
} from '@angular/core';
|
|
|
|
|
|
|
|
import { fromEvent } from 'rxjs';
|
|
|
|
|
|
|
|
import { debounceTime } from 'rxjs/operators';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Component({
|
|
|
|
@Component({
|
|
|
|
selector: 'app-routes',
|
|
|
|
selector: 'app-routes',
|
|
|
|
templateUrl: 'routes.component.html',
|
|
|
|
templateUrl: 'routes.component.html',
|
|
|
|
})
|
|
|
|
})
|
|
|
|
export class RoutesComponent implements AfterViewInit {
|
|
|
|
export class RoutesComponent {
|
|
|
|
@HostBinding('class.mx-auto')
|
|
|
|
@HostBinding('class.mx-auto')
|
|
|
|
marginAuto = true;
|
|
|
|
marginAuto = true;
|
|
|
|
|
|
|
|
|
|
|
|
smallScreen = window.innerWidth < 992;
|
|
|
|
get smallScreen() {
|
|
|
|
|
|
|
|
return window.innerWidth < 992;
|
|
|
|
constructor(private renderer: Renderer2) {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ngAfterViewInit() {
|
|
|
|
|
|
|
|
fromEvent(window, 'resize')
|
|
|
|
|
|
|
|
.pipe(debounceTime(150))
|
|
|
|
|
|
|
|
.subscribe(() => {
|
|
|
|
|
|
|
|
this.smallScreen = window.innerWidth < 992;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
```
|
|
|
@ -310,7 +291,7 @@ Open `app.component.ts` in `src/app` folder and modify it as shown below:
|
|
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
```js
|
|
|
|
import { ..., ReplaceableComponentsService } from '@abp/ng.core'; // imported ReplaceableComponentsService
|
|
|
|
import { ..., ReplaceableComponentsService } from '@abp/ng.core'; // imported ReplaceableComponentsService
|
|
|
|
import { RoutesComponent } from './routes/routes.component'; // imported NavItemsComponent
|
|
|
|
import { RoutesComponent } from './routes/routes.component'; // imported RoutesComponent
|
|
|
|
import { eThemeBasicComponents } from '@abp/ng.theme.basic'; // imported eThemeBasicComponents
|
|
|
|
import { eThemeBasicComponents } from '@abp/ng.theme.basic'; // imported eThemeBasicComponents
|
|
|
|
//...
|
|
|
|
//...
|
|
|
|
|
|
|
|
|
|
|
@ -347,51 +328,51 @@ Open the generated `nav-items.component.ts` in `src/app/nav-items` folder and re
|
|
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
```js
|
|
|
|
import {
|
|
|
|
import {
|
|
|
|
ApplicationConfiguration,
|
|
|
|
|
|
|
|
AuthService,
|
|
|
|
AuthService,
|
|
|
|
ConfigState,
|
|
|
|
ConfigStateService,
|
|
|
|
|
|
|
|
CurrentUserDto,
|
|
|
|
|
|
|
|
LanguageInfo,
|
|
|
|
|
|
|
|
NAVIGATE_TO_MANAGE_PROFILE,
|
|
|
|
SessionStateService,
|
|
|
|
SessionStateService,
|
|
|
|
SetLanguage,
|
|
|
|
|
|
|
|
} from '@abp/ng.core';
|
|
|
|
} from '@abp/ng.core';
|
|
|
|
import { Component, AfterViewInit } from '@angular/core';
|
|
|
|
import { Component, Inject } from '@angular/core';
|
|
|
|
import { Navigate, RouterState } from '@ngxs/router-plugin';
|
|
|
|
import { Observable } from 'rxjs';
|
|
|
|
import { Select, Store } from '@ngxs/store';
|
|
|
|
import { map } from 'rxjs/operators';
|
|
|
|
import { Observable, fromEvent } from 'rxjs';
|
|
|
|
|
|
|
|
import { map, debounceTime } from 'rxjs/operators';
|
|
|
|
|
|
|
|
import snq from 'snq';
|
|
|
|
import snq from 'snq';
|
|
|
|
|
|
|
|
|
|
|
|
@Component({
|
|
|
|
@Component({
|
|
|
|
selector: 'app-nav-items',
|
|
|
|
selector: 'app-nav-items',
|
|
|
|
templateUrl: 'nav-items.component.html',
|
|
|
|
templateUrl: 'nav-items.component.html',
|
|
|
|
})
|
|
|
|
})
|
|
|
|
export class NavItemsComponent implements AfterViewInit {
|
|
|
|
export class NavItemsComponent {
|
|
|
|
@Select(ConfigState.getOne('currentUser'))
|
|
|
|
currentUser$: Observable<CurrentUserDto> = this.configState.getOne$('currentUser');
|
|
|
|
currentUser$: Observable<ApplicationConfiguration.CurrentUser>;
|
|
|
|
selectedTenant$ = this.sessionState.getTenant$();
|
|
|
|
|
|
|
|
|
|
|
|
@Select(ConfigState.getDeep('localization.languages'))
|
|
|
|
languages$: Observable<LanguageInfo[]> = this.configState.getDeep$('localization.languages');
|
|
|
|
languages$: Observable<ApplicationConfiguration.Language[]>;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
smallScreen = window.innerWidth < 992;
|
|
|
|
get smallScreen(): boolean {
|
|
|
|
|
|
|
|
return window.innerWidth < 992;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
get defaultLanguage$(): Observable<string> {
|
|
|
|
get defaultLanguage$(): Observable<string> {
|
|
|
|
return this.languages$.pipe(
|
|
|
|
return this.languages$.pipe(
|
|
|
|
map(
|
|
|
|
map(
|
|
|
|
languages =>
|
|
|
|
languages =>
|
|
|
|
snq(
|
|
|
|
snq(
|
|
|
|
() => languages.find(lang => lang.cultureName === this.selectedLangCulture).displayName,
|
|
|
|
() => languages.find(lang => lang.cultureName === this.selectedLangCulture).displayName
|
|
|
|
),
|
|
|
|
),
|
|
|
|
'',
|
|
|
|
''
|
|
|
|
),
|
|
|
|
)
|
|
|
|
);
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
get dropdownLanguages$(): Observable<ApplicationConfiguration.Language[]> {
|
|
|
|
get dropdownLanguages$(): Observable<LanguageInfo[]> {
|
|
|
|
return this.languages$.pipe(
|
|
|
|
return this.languages$.pipe(
|
|
|
|
map(
|
|
|
|
map(
|
|
|
|
languages =>
|
|
|
|
languages =>
|
|
|
|
snq(() => languages.filter(lang => lang.cultureName !== this.selectedLangCulture)),
|
|
|
|
snq(() => languages.filter(lang => lang.cultureName !== this.selectedLangCulture)),
|
|
|
|
[],
|
|
|
|
[]
|
|
|
|
),
|
|
|
|
)
|
|
|
|
);
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -399,28 +380,23 @@ export class NavItemsComponent implements AfterViewInit {
|
|
|
|
return this.sessionState.getLanguage();
|
|
|
|
return this.sessionState.getLanguage();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
constructor(private store: Store, private authService: AuthService, private sessionState: SessionStateService) {}
|
|
|
|
constructor(
|
|
|
|
|
|
|
|
@Inject(NAVIGATE_TO_MANAGE_PROFILE) public navigateToManageProfile,
|
|
|
|
|
|
|
|
private configState: ConfigStateService,
|
|
|
|
|
|
|
|
private authService: AuthService,
|
|
|
|
|
|
|
|
private sessionState: SessionStateService
|
|
|
|
|
|
|
|
) {}
|
|
|
|
|
|
|
|
|
|
|
|
ngAfterViewInit() {
|
|
|
|
onChangeLang(cultureName: string) {
|
|
|
|
fromEvent(window, 'resize')
|
|
|
|
this.sessionState.setLanguage(cultureName);
|
|
|
|
.pipe(debounceTime(150))
|
|
|
|
|
|
|
|
.subscribe(() => {
|
|
|
|
|
|
|
|
this.smallScreen = window.innerWidth < 992;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
onChangeLang(cultureName: string) {
|
|
|
|
navigateToLogin() {
|
|
|
|
this.store.dispatch(new SetLanguage(cultureName));
|
|
|
|
this.authService.navigateToLogin();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
logout() {
|
|
|
|
logout() {
|
|
|
|
this.authService.logout().subscribe(() => {
|
|
|
|
this.authService.logout().subscribe();
|
|
|
|
this.store.dispatch(
|
|
|
|
|
|
|
|
new Navigate(['/'], null, {
|
|
|
|
|
|
|
|
state: { redirectUrl: this.store.selectSnapshot(RouterState).state.url },
|
|
|
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
```
|
|
|
@ -445,8 +421,14 @@ Open the generated `nav-items.component.html` in `src/app/nav-items` folder and
|
|
|
|
```html
|
|
|
|
```html
|
|
|
|
<ul class="navbar-nav">
|
|
|
|
<ul class="navbar-nav">
|
|
|
|
<input type="search" placeholder="Search" class="bg-transparent border-0 text-white" />
|
|
|
|
<input type="search" placeholder="Search" class="bg-transparent border-0 text-white" />
|
|
|
|
<li *ngIf="(dropdownLanguages$ | async)?.length > 0" class="nav-item">
|
|
|
|
<li class="nav-item d-flex align-items-center">
|
|
|
|
<div class="dropdown" ngbDropdown #languageDropdown="ngbDropdown" display="static">
|
|
|
|
<div
|
|
|
|
|
|
|
|
*ngIf="(dropdownLanguages$ | async)?.length > 0"
|
|
|
|
|
|
|
|
class="dropdown"
|
|
|
|
|
|
|
|
ngbDropdown
|
|
|
|
|
|
|
|
#languageDropdown="ngbDropdown"
|
|
|
|
|
|
|
|
display="static"
|
|
|
|
|
|
|
|
>
|
|
|
|
<a
|
|
|
|
<a
|
|
|
|
ngbDropdownToggle
|
|
|
|
ngbDropdownToggle
|
|
|
|
class="nav-link"
|
|
|
|
class="nav-link"
|
|
|
@ -474,10 +456,9 @@ Open the generated `nav-items.component.html` in `src/app/nav-items` folder and
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</li>
|
|
|
|
</li>
|
|
|
|
|
|
|
|
<li class="nav-item d-flex align-items-center">
|
|
|
|
<li class="nav-item">
|
|
|
|
|
|
|
|
<ng-template #loginBtn>
|
|
|
|
<ng-template #loginBtn>
|
|
|
|
<a role="button" class="nav-link" routerLink="/account/login">{%{{{
|
|
|
|
<a role="button" class="nav-link pointer" (click)="navigateToLogin()">{%{{{
|
|
|
|
'AbpAccount::Login' | abpLocalization
|
|
|
|
'AbpAccount::Login' | abpLocalization
|
|
|
|
}}}%}</a>
|
|
|
|
}}}%}</a>
|
|
|
|
</ng-template>
|
|
|
|
</ng-template>
|
|
|
@ -498,14 +479,18 @@ Open the generated `nav-items.component.html` in `src/app/nav-items` folder and
|
|
|
|
aria-haspopup="true"
|
|
|
|
aria-haspopup="true"
|
|
|
|
aria-expanded="false"
|
|
|
|
aria-expanded="false"
|
|
|
|
>
|
|
|
|
>
|
|
|
|
{%{{{ (currentUser$ | async)?.userName }}}%}
|
|
|
|
<small *ngIf="(selectedTenant$ | async)?.name as tenantName"
|
|
|
|
|
|
|
|
><i>{%{{{ tenantName }}}%}</i
|
|
|
|
|
|
|
|
>\</small
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<strong>{%{{{ (currentUser$ | async)?.userName }}}%}</strong>
|
|
|
|
</a>
|
|
|
|
</a>
|
|
|
|
<div
|
|
|
|
<div
|
|
|
|
class="dropdown-menu dropdown-menu-right border-0 shadow-sm"
|
|
|
|
class="dropdown-menu dropdown-menu-right border-0 shadow-sm"
|
|
|
|
aria-labelledby="dropdownMenuLink"
|
|
|
|
aria-labelledby="dropdownMenuLink"
|
|
|
|
[class.d-block]="smallScreen && currentUserDropdown.isOpen()"
|
|
|
|
[class.d-block]="smallScreen && currentUserDropdown.isOpen()"
|
|
|
|
>
|
|
|
|
>
|
|
|
|
<a class="dropdown-item" routerLink="/account/manage-profile"
|
|
|
|
<a class="dropdown-item pointer" (click)="navigateToManageProfile()"
|
|
|
|
><i class="fa fa-cog mr-1"></i>{%{{{ 'AbpAccount::ManageYourProfile' | abpLocalization }}}%}</a
|
|
|
|
><i class="fa fa-cog mr-1"></i>{%{{{ 'AbpAccount::ManageYourProfile' | abpLocalization }}}%}</a
|
|
|
|
>
|
|
|
|
>
|
|
|
|
<a class="dropdown-item" href="javascript:void(0)" (click)="logout()"
|
|
|
|
<a class="dropdown-item" href="javascript:void(0)" (click)="logout()"
|
|
|
|