From 24e727ec4a6e5049c7eda277e4e4ec413c610a14 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Thu, 18 Jun 2020 18:07:00 +0300 Subject: [PATCH 01/13] chore: remove nav-item.utils --- .../theme-shared/src/lib/utils/index.ts | 1 - .../theme-shared/src/lib/utils/nav-items.ts | 22 ------------------- 2 files changed, 23 deletions(-) delete mode 100644 npm/ng-packs/packages/theme-shared/src/lib/utils/nav-items.ts diff --git a/npm/ng-packs/packages/theme-shared/src/lib/utils/index.ts b/npm/ng-packs/packages/theme-shared/src/lib/utils/index.ts index f1d694dded..9f290b5ca3 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/utils/index.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/utils/index.ts @@ -1,4 +1,3 @@ export * from './date-parser-formatter'; -export * from './nav-items'; export * from './validation-utils'; export * from './widget-utils'; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/utils/nav-items.ts b/npm/ng-packs/packages/theme-shared/src/lib/utils/nav-items.ts deleted file mode 100644 index b6b002a151..0000000000 --- a/npm/ng-packs/packages/theme-shared/src/lib/utils/nav-items.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Type } from '@angular/core'; -import { ReplaySubject } from 'rxjs'; - -export interface NavItem { - component?: Type; - html?: string; - action?: () => void; - order?: number; - permission?: string; -} - -const navItems: NavItem[] = []; -const navItems$ = new ReplaySubject(1); - -export function addNavItem(item: NavItem) { - navItems.push(item); - navItems$.next(navItems.sort((a, b) => (a.order ? a.order - b.order : 1))); -} - -export function getNavItems() { - return navItems$.asObservable(); -} From 32cb41de7e5ad07b83ec788c454ef2a53e7ccf0c Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Thu, 18 Jun 2020 18:07:31 +0300 Subject: [PATCH 02/13] feat(theme-shared): create nav-items.service --- .../theme-shared/src/lib/services/index.ts | 1 + .../src/lib/services/nav-items.service.ts | 49 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 npm/ng-packs/packages/theme-shared/src/lib/services/nav-items.service.ts diff --git a/npm/ng-packs/packages/theme-shared/src/lib/services/index.ts b/npm/ng-packs/packages/theme-shared/src/lib/services/index.ts index c363a56894..29a2ca9668 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/services/index.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/services/index.ts @@ -1,3 +1,4 @@ export * from './confirmation.service'; export * from './modal.service'; export * from './toaster.service'; +export * from './nav-items.service'; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/services/nav-items.service.ts b/npm/ng-packs/packages/theme-shared/src/lib/services/nav-items.service.ts new file mode 100644 index 0000000000..95403837fd --- /dev/null +++ b/npm/ng-packs/packages/theme-shared/src/lib/services/nav-items.service.ts @@ -0,0 +1,49 @@ +import { Injectable } from '@angular/core'; +import { BehaviorSubject, Observable } from 'rxjs'; +import { NavItem } from '../models/nav-item'; + +@Injectable({ providedIn: 'root' }) +export class NavItemsService { + private _items$ = new BehaviorSubject([]); + + get items(): NavItem[] { + return this._items$.value; + } + + get items$(): Observable { + return this._items$.asObservable(); + } + + addItems(items: NavItem[]) { + this._items$.next([...this.items, ...items].sort(sortItems)); + } + + removeItem(id: string | number) { + const index = this.items.findIndex(item => item.id === id); + + if (index > -1) { + this._items$.next([...this.items.slice(0, index), ...this.items.slice(index + 1)]); + } + } + + patchItem(id: string | number, item: Partial>) { + const index = this.items.findIndex(i => i.id === id); + + if (index > -1) { + this._items$.next( + [ + ...this.items.slice(0, index), + { ...this.items[index], ...item }, + ...this.items.slice(index + 1), + ].sort(sortItems), + ); + } + } +} + +function sortItems(a: NavItem, b: NavItem) { + if (!a.order) return 1; + if (!b.order) return -1; + + return a.order < b.order ? -1 : 1; +} From f2cb8a00b60740d77f7f43735c53509e73701eb3 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Thu, 18 Jun 2020 18:07:50 +0300 Subject: [PATCH 03/13] feat: create nav-item interface --- .../packages/theme-shared/src/lib/models/index.ts | 1 + .../packages/theme-shared/src/lib/models/nav-item.ts | 10 ++++++++++ 2 files changed, 11 insertions(+) create mode 100644 npm/ng-packs/packages/theme-shared/src/lib/models/nav-item.ts diff --git a/npm/ng-packs/packages/theme-shared/src/lib/models/index.ts b/npm/ng-packs/packages/theme-shared/src/lib/models/index.ts index 628ce6d80d..d1e2e71c5c 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/models/index.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/models/index.ts @@ -2,3 +2,4 @@ export * from './common'; export * from './confirmation'; export * from './statistics'; export * from './toaster'; +export * from './nav-item'; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/models/nav-item.ts b/npm/ng-packs/packages/theme-shared/src/lib/models/nav-item.ts new file mode 100644 index 0000000000..ea3d5c45a2 --- /dev/null +++ b/npm/ng-packs/packages/theme-shared/src/lib/models/nav-item.ts @@ -0,0 +1,10 @@ +import { Type } from '@angular/core'; + +export interface NavItem { + id: string | number; + component?: Type; + html?: string; + action?: () => void; + order?: number; + requiredPolicy?: string; +} From 79afc3e6aba0358e670f0e4d9d0e10fe51509219 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Thu, 18 Jun 2020 18:08:12 +0300 Subject: [PATCH 04/13] chore: remove layout state --- .../theme-basic/src/lib/actions/index.ts | 1 - .../src/lib/actions/layout.actions.ts | 11 --- .../src/lib/services/layout-state.service.ts | 24 ------- .../theme-basic/src/lib/states/index.ts | 1 - .../src/lib/states/layout.state.ts | 67 ------------------- .../lib/tests/layout-state.service.spec.ts | 57 ---------------- .../theme-basic/src/lib/theme-basic.module.ts | 23 ++++--- .../packages/theme-basic/src/public-api.ts | 2 - 8 files changed, 13 insertions(+), 173 deletions(-) delete mode 100644 npm/ng-packs/packages/theme-basic/src/lib/actions/index.ts delete mode 100644 npm/ng-packs/packages/theme-basic/src/lib/actions/layout.actions.ts delete mode 100644 npm/ng-packs/packages/theme-basic/src/lib/services/layout-state.service.ts delete mode 100644 npm/ng-packs/packages/theme-basic/src/lib/states/index.ts delete mode 100644 npm/ng-packs/packages/theme-basic/src/lib/states/layout.state.ts delete mode 100644 npm/ng-packs/packages/theme-basic/src/lib/tests/layout-state.service.spec.ts diff --git a/npm/ng-packs/packages/theme-basic/src/lib/actions/index.ts b/npm/ng-packs/packages/theme-basic/src/lib/actions/index.ts deleted file mode 100644 index 2e29080de8..0000000000 --- a/npm/ng-packs/packages/theme-basic/src/lib/actions/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './layout.actions'; diff --git a/npm/ng-packs/packages/theme-basic/src/lib/actions/layout.actions.ts b/npm/ng-packs/packages/theme-basic/src/lib/actions/layout.actions.ts deleted file mode 100644 index 3786ea82b7..0000000000 --- a/npm/ng-packs/packages/theme-basic/src/lib/actions/layout.actions.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Layout } from '../models/layout'; - -export class AddNavigationElement { - static readonly type = '[Layout] Add Navigation Element'; - constructor(public payload: Layout.NavigationElement | Layout.NavigationElement[]) {} -} - -export class RemoveNavigationElementByName { - static readonly type = '[Layout] Remove Navigation ElementByName'; - constructor(public name: string) {} -} diff --git a/npm/ng-packs/packages/theme-basic/src/lib/services/layout-state.service.ts b/npm/ng-packs/packages/theme-basic/src/lib/services/layout-state.service.ts deleted file mode 100644 index 415cef61d3..0000000000 --- a/npm/ng-packs/packages/theme-basic/src/lib/services/layout-state.service.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Injectable } from '@angular/core'; -import { Store } from '@ngxs/store'; -import { LayoutState } from '../states/layout.state'; -import { AddNavigationElement, RemoveNavigationElementByName } from '../actions'; -import { Layout } from '../models/layout'; - -@Injectable({ providedIn: 'root' }) -export class LayoutStateService { - constructor(private store: Store) {} - - getNavigationElements() { - return this.store.selectSnapshot(LayoutState.getNavigationElements); - } - - dispatchAddNavigationElement(...args: ConstructorParameters) { - return this.store.dispatch(new AddNavigationElement(...args)); - } - - dispatchRemoveNavigationElementByName( - ...args: ConstructorParameters - ) { - return this.store.dispatch(new RemoveNavigationElementByName(...args)); - } -} diff --git a/npm/ng-packs/packages/theme-basic/src/lib/states/index.ts b/npm/ng-packs/packages/theme-basic/src/lib/states/index.ts deleted file mode 100644 index 1e257fc64c..0000000000 --- a/npm/ng-packs/packages/theme-basic/src/lib/states/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './layout.state'; diff --git a/npm/ng-packs/packages/theme-basic/src/lib/states/layout.state.ts b/npm/ng-packs/packages/theme-basic/src/lib/states/layout.state.ts deleted file mode 100644 index 93f4352d69..0000000000 --- a/npm/ng-packs/packages/theme-basic/src/lib/states/layout.state.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { Injectable } from '@angular/core'; -import { Action, Selector, State, StateContext } from '@ngxs/store'; -import snq from 'snq'; -import { AddNavigationElement, RemoveNavigationElementByName } from '../actions/layout.actions'; -import { Layout } from '../models/layout'; - -@State({ - name: 'LayoutState', - defaults: { navigationElements: [] } as Layout.State, -}) -@Injectable() -export class LayoutState { - @Selector() - static getNavigationElements({ navigationElements }: Layout.State): Layout.NavigationElement[] { - return navigationElements; - } - - @Action(AddNavigationElement) - layoutAddAction( - { getState, patchState }: StateContext, - { payload = [] }: AddNavigationElement, - ) { - let { navigationElements } = getState(); - - if (!Array.isArray(payload)) { - payload = [payload]; - } - - if (navigationElements.length) { - payload = snq( - () => - (payload as Layout.NavigationElement[]).filter( - ({ name }) => navigationElements.findIndex(nav => nav.name === name) < 0, - ), - [], - ); - } - - if (!payload.length) return; - - navigationElements = [...navigationElements, ...payload] - .map(element => ({ ...element, order: element.order || 99 })) - .sort((a, b) => a.order - b.order); - - return patchState({ - navigationElements, - }); - } - - @Action(RemoveNavigationElementByName) - layoutRemoveAction( - { getState, patchState }: StateContext, - { name }: RemoveNavigationElementByName, - ) { - let { navigationElements } = getState(); - - const index = navigationElements.findIndex(element => element.name === name); - - if (index > -1) { - navigationElements = navigationElements.splice(index, 1); - } - - return patchState({ - navigationElements, - }); - } -} diff --git a/npm/ng-packs/packages/theme-basic/src/lib/tests/layout-state.service.spec.ts b/npm/ng-packs/packages/theme-basic/src/lib/tests/layout-state.service.spec.ts deleted file mode 100644 index de4f489aaa..0000000000 --- a/npm/ng-packs/packages/theme-basic/src/lib/tests/layout-state.service.spec.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { createServiceFactory, SpectatorService, SpyObject } from '@ngneat/spectator/jest'; -import { Store } from '@ngxs/store'; -import * as LayoutActions from '../actions'; -import { LayoutStateService } from '../services/layout-state.service'; -import { LayoutState } from '../states/layout.state'; -describe('LayoutStateService', () => { - let service: LayoutStateService; - let spectator: SpectatorService; - let store: SpyObject; - - const createService = createServiceFactory({ service: LayoutStateService, mocks: [Store] }); - beforeEach(() => { - spectator = createService(); - service = spectator.service; - store = spectator.get(Store); - }); - - test('should have the all LayoutState static methods', () => { - const reg = /(?<=static )(.*)(?=\()/gm; - LayoutState.toString() - .match(reg) - .forEach(fnName => { - expect(service[fnName]).toBeTruthy(); - - const spy = jest.spyOn(store, 'selectSnapshot'); - spy.mockClear(); - - const isDynamicSelector = LayoutState[fnName].name !== 'memoized'; - - if (isDynamicSelector) { - LayoutState[fnName] = jest.fn((...args) => args); - service[fnName]('test', 0, {}); - expect(LayoutState[fnName]).toHaveBeenCalledWith('test', 0, {}); - } else { - service[fnName](); - expect(spy).toHaveBeenCalledWith(LayoutState[fnName]); - } - }); - }); - - test('should have a dispatch method for every LayoutState action', () => { - const reg = /(?<=dispatch)(\w+)(?=\()/gm; - LayoutStateService.toString() - .match(reg) - .forEach(fnName => { - expect(LayoutActions[fnName]).toBeTruthy(); - - const spy = jest.spyOn(store, 'dispatch'); - spy.mockClear(); - - const params = Array.from(new Array(LayoutActions[fnName].length)); - - service[`dispatch${fnName}`](...params); - expect(spy).toHaveBeenCalledWith(new LayoutActions[fnName](...params)); - }); - }); -}); diff --git a/npm/ng-packs/packages/theme-basic/src/lib/theme-basic.module.ts b/npm/ng-packs/packages/theme-basic/src/lib/theme-basic.module.ts index 0a91c83fc7..cf94786e36 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/theme-basic.module.ts +++ b/npm/ng-packs/packages/theme-basic/src/lib/theme-basic.module.ts @@ -3,7 +3,6 @@ import { ThemeSharedModule } from '@abp/ng.theme.shared'; import { NgModule } from '@angular/core'; import { NgbCollapseModule, NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap'; import { NgxValidateCoreModule } from '@ngx-validate/core'; -import { NgxsModule } from '@ngxs/store'; import { AccountLayoutComponent } from './components/account-layout/account-layout.component'; import { ApplicationLayoutComponent } from './components/application-layout/application-layout.component'; import { EmptyLayoutComponent } from './components/empty-layout/empty-layout.component'; @@ -12,7 +11,8 @@ import { NavItemsComponent } from './components/nav-items/nav-items.component'; import { RoutesComponent } from './components/routes/routes.component'; import { ValidationErrorComponent } from './components/validation-error/validation-error.component'; import { InitialService } from './services/initial.service'; -import { LayoutState } from './states/layout.state'; +import { CurrentUserComponent } from './components/nav-items/current-user.component'; +import { LanguagesComponent } from './components/nav-items/languages.component'; export const LAYOUTS = [ApplicationLayoutComponent, AccountLayoutComponent, EmptyLayoutComponent]; @@ -23,6 +23,17 @@ export const LAYOUTS = [ApplicationLayoutComponent, AccountLayoutComponent, Empt LogoComponent, NavItemsComponent, RoutesComponent, + CurrentUserComponent, + LanguagesComponent, + ], + exports: [ + ...LAYOUTS, + ValidationErrorComponent, + LogoComponent, + NavItemsComponent, + RoutesComponent, + CurrentUserComponent, + LanguagesComponent, ], imports: [ CoreModule, @@ -30,7 +41,6 @@ export const LAYOUTS = [ApplicationLayoutComponent, AccountLayoutComponent, Empt NgbCollapseModule, NgbDropdownModule, NgxValidateCoreModule, - NgxsModule.forFeature([LayoutState]), NgxValidateCoreModule.forRoot({ targetSelector: '.form-group', blueprints: { @@ -52,13 +62,6 @@ export const LAYOUTS = [ApplicationLayoutComponent, AccountLayoutComponent, Empt errorTemplate: ValidationErrorComponent, }), ], - exports: [ - ...LAYOUTS, - ValidationErrorComponent, - LogoComponent, - NavItemsComponent, - RoutesComponent, - ], entryComponents: [...LAYOUTS, ValidationErrorComponent], }) export class ThemeBasicModule { diff --git a/npm/ng-packs/packages/theme-basic/src/public-api.ts b/npm/ng-packs/packages/theme-basic/src/public-api.ts index 580366dbcb..033a8d2d82 100644 --- a/npm/ng-packs/packages/theme-basic/src/public-api.ts +++ b/npm/ng-packs/packages/theme-basic/src/public-api.ts @@ -3,9 +3,7 @@ */ export * from './lib/theme-basic.module'; -export * from './lib/actions'; export * from './lib/components'; export * from './lib/enums'; export * from './lib/models'; export * from './lib/services'; -export * from './lib/states'; From 5c3aabda5de77150dd9d26432fc59ed8f7525c2b Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Thu, 18 Jun 2020 18:08:25 +0300 Subject: [PATCH 05/13] feat: create CurrentUserComponent --- .../nav-items/current-user.component.ts | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.ts diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.ts b/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.ts new file mode 100644 index 0000000000..70238d3538 --- /dev/null +++ b/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.ts @@ -0,0 +1,67 @@ +import { ApplicationConfiguration, AuthService, ConfigState } from '@abp/ng.core'; +import { Component, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; +import { Select } from '@ngxs/store'; +import { Observable } from 'rxjs'; + +@Component({ + selector: 'abp-current-user', + // tslint:disable-next-line: component-max-inline-declarations + template: ` + + {{ + 'AbpAccount::Login' | abpLocalization + }} + + + `, +}) +export class CurrentUserComponent implements OnInit { + @Select(ConfigState.getOne('currentUser')) + currentUser$: Observable; + + get smallScreen(): boolean { + return window.innerWidth < 992; + } + + constructor(private authService: AuthService, private router: Router) {} + + ngOnInit() {} + + logout() { + this.authService.logout().subscribe(() => { + this.router.navigate(['/'], { state: { redirectUrl: this.router.url } }); + }); + } +} From f9534214291d833dfb437c1c6e464b8c2b5449a2 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Thu, 18 Jun 2020 18:08:33 +0300 Subject: [PATCH 06/13] feat: create LanguagesComponent --- .../nav-items/languages.component.ts | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/languages.component.ts diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/languages.component.ts b/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/languages.component.ts new file mode 100644 index 0000000000..115e9e563e --- /dev/null +++ b/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/languages.component.ts @@ -0,0 +1,88 @@ +import { Component, OnInit, Input } from '@angular/core'; +import { Store, Select } from '@ngxs/store'; +import { SetLanguage, ConfigState, ApplicationConfiguration, SessionState } from '@abp/ng.core'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; +import snq from 'snq'; + +@Component({ + selector: 'abp-languages', + // tslint:disable-next-line: component-max-inline-declarations + template: ` + + `, +}) +export class LanguagesComponent implements OnInit { + get smallScreen(): boolean { + return window.innerWidth < 992; + } + + @Select(ConfigState.getDeep('localization.languages')) + languages$: Observable; + + get defaultLanguage$(): Observable { + return this.languages$.pipe( + map( + languages => + snq( + () => languages.find(lang => lang.cultureName === this.selectedLangCulture).displayName, + ), + '', + ), + ); + } + + get dropdownLanguages$(): Observable { + return this.languages$.pipe( + map( + languages => + snq(() => languages.filter(lang => lang.cultureName !== this.selectedLangCulture)), + [], + ), + ); + } + + get selectedLangCulture(): string { + return this.store.selectSnapshot(SessionState.getLanguage); + } + + constructor(private store: Store) {} + + ngOnInit() {} + + onChangeLang(cultureName: string) { + this.store.dispatch(new SetLanguage(cultureName)); + } +} From 2b3baba52aaed9f1316437ffb9f700887c92e389 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Thu, 18 Jun 2020 18:09:03 +0300 Subject: [PATCH 07/13] refactor: move languages and current user logics to related components --- .../theme-basic/src/lib/components/index.ts | 2 + .../nav-items/nav-items.component.html | 89 ++----------- .../nav-items/nav-items.component.ts | 123 +----------------- 3 files changed, 19 insertions(+), 195 deletions(-) diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/index.ts b/npm/ng-packs/packages/theme-basic/src/lib/components/index.ts index 06b6d5339c..6c4de6cf21 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/components/index.ts +++ b/npm/ng-packs/packages/theme-basic/src/lib/components/index.ts @@ -2,6 +2,8 @@ export * from './account-layout/account-layout.component'; export * from './application-layout/application-layout.component'; export * from './empty-layout/empty-layout.component'; export * from './logo/logo.component'; +export * from './nav-items/current-user.component'; +export * from './nav-items/languages.component'; export * from './nav-items/nav-items.component'; export * from './routes/routes.component'; export * from './validation-error/validation-error.component'; diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/nav-items.component.html b/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/nav-items.component.html index cb86773db5..955ccb8878 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/nav-items.component.html +++ b/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/nav-items.component.html @@ -1,81 +1,16 @@ - - - - + - + diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/nav-items.component.ts b/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/nav-items.component.ts index 6819807cd7..7a5ee9b37a 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/nav-items.component.ts +++ b/npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/nav-items.component.ts @@ -1,125 +1,12 @@ -import { - ABP, - ApplicationConfiguration, - AuthService, - ConfigState, - SessionState, - SetLanguage, - takeUntilDestroy, -} from '@abp/ng.core'; -import { - AfterViewInit, - Component, - Input, - OnDestroy, - TemplateRef, - TrackByFunction, - ViewChild, -} from '@angular/core'; -import { Navigate, RouterState } from '@ngxs/router-plugin'; -import { Select, Store } from '@ngxs/store'; -import compare from 'just-compare'; -import { Observable } from 'rxjs'; -import { filter, map } from 'rxjs/operators'; -import snq from 'snq'; -import { AddNavigationElement } from '../../actions/layout.actions'; -import { eNavigationElementNames } from '../../enums/navigation-element-names'; -import { Layout } from '../../models/layout'; -import { LayoutState } from '../../states/layout.state'; +import { NavItem, NavItemsService } from '@abp/ng.theme.shared'; +import { Component, Input, TrackByFunction } from '@angular/core'; @Component({ selector: 'abp-nav-items', templateUrl: 'nav-items.component.html', }) -export class NavItemsComponent implements AfterViewInit, OnDestroy { - @Select(LayoutState.getNavigationElements) - navElements$: Observable; +export class NavItemsComponent { + trackByFn: TrackByFunction = (_, element) => element.id; - @Select(ConfigState.getOne('currentUser')) - currentUser$: Observable; - - @Select(ConfigState.getDeep('localization.languages')) - languages$: Observable; - - @ViewChild('currentUser', { static: false, read: TemplateRef }) - currentUserRef: TemplateRef; - - @ViewChild('language', { static: false, read: TemplateRef }) - languageRef: TemplateRef; - - @Input() - smallScreen: boolean; - - rightPartElements: TemplateRef[] = []; - - trackByFn: TrackByFunction = (_, element) => element.name; - - get defaultLanguage$(): Observable { - return this.languages$.pipe( - map( - languages => - snq( - () => languages.find(lang => lang.cultureName === this.selectedLangCulture).displayName, - ), - '', - ), - ); - } - - get dropdownLanguages$(): Observable { - return this.languages$.pipe( - map( - languages => - snq(() => languages.filter(lang => lang.cultureName !== this.selectedLangCulture)), - [], - ), - ); - } - - get selectedLangCulture(): string { - return this.store.selectSnapshot(SessionState.getLanguage); - } - - constructor(private store: Store, private authService: AuthService) {} - - ngAfterViewInit() { - const navigations = this.store - .selectSnapshot(LayoutState.getNavigationElements) - .map(({ name }) => name); - - if (navigations.indexOf(eNavigationElementNames.Language) < 0) { - this.store.dispatch( - new AddNavigationElement([ - { element: this.languageRef, order: 4, name: eNavigationElementNames.Language }, - { element: this.currentUserRef, order: 5, name: eNavigationElementNames.User }, - ]), - ); - } - - this.navElements$ - .pipe( - map(elements => elements.map(({ element }) => element)), - filter(elements => !compare(elements, this.rightPartElements)), - takeUntilDestroy(this), - ) - .subscribe(elements => { - setTimeout(() => (this.rightPartElements = elements), 0); - }); - } - - ngOnDestroy() {} - - onChangeLang(cultureName: string) { - this.store.dispatch(new SetLanguage(cultureName)); - } - - logout() { - this.authService.logout().subscribe(() => { - this.store.dispatch( - new Navigate(['/'], null, { - state: { redirectUrl: this.store.selectSnapshot(RouterState).state.url }, - }), - ); - }); - } + constructor(public readonly navItems: NavItemsService) {} } From 6e2b64d776d898e8af166979ec31a669955680b1 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Thu, 18 Jun 2020 18:09:16 +0300 Subject: [PATCH 08/13] chore: remove an input --- .../application-layout/application-layout.component.html | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/application-layout/application-layout.component.html b/npm/ng-packs/packages/theme-basic/src/lib/components/application-layout/application-layout.component.html index c4acbec880..bb34ec33f6 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/components/application-layout/application-layout.component.html +++ b/npm/ng-packs/packages/theme-basic/src/lib/components/application-layout/application-layout.component.html @@ -34,12 +34,8 @@ From 8e7018214bfc02d34b00025f4fe4d20cc9e25b51 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Thu, 18 Jun 2020 18:09:29 +0300 Subject: [PATCH 09/13] chore: remove eNavigationElementNames --- npm/ng-packs/packages/theme-basic/src/lib/enums/index.ts | 1 - .../theme-basic/src/lib/enums/navigation-element-names.ts | 4 ---- 2 files changed, 5 deletions(-) delete mode 100644 npm/ng-packs/packages/theme-basic/src/lib/enums/navigation-element-names.ts diff --git a/npm/ng-packs/packages/theme-basic/src/lib/enums/index.ts b/npm/ng-packs/packages/theme-basic/src/lib/enums/index.ts index 51f9e1ead1..07635cbbc8 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/enums/index.ts +++ b/npm/ng-packs/packages/theme-basic/src/lib/enums/index.ts @@ -1,2 +1 @@ export * from './components'; -export * from './navigation-element-names'; diff --git a/npm/ng-packs/packages/theme-basic/src/lib/enums/navigation-element-names.ts b/npm/ng-packs/packages/theme-basic/src/lib/enums/navigation-element-names.ts deleted file mode 100644 index 12aa3f0941..0000000000 --- a/npm/ng-packs/packages/theme-basic/src/lib/enums/navigation-element-names.ts +++ /dev/null @@ -1,4 +0,0 @@ -export const enum eNavigationElementNames { - Language = 'LanguageRef', - User = 'CurrentUserRef', -} From a934c0f6bc81cfb2d5fa9b14005ef115a28193c9 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Thu, 18 Jun 2020 18:09:58 +0300 Subject: [PATCH 10/13] chore: add new component names to components enum --- npm/ng-packs/packages/theme-basic/src/lib/enums/components.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/npm/ng-packs/packages/theme-basic/src/lib/enums/components.ts b/npm/ng-packs/packages/theme-basic/src/lib/enums/components.ts index ab7aa86942..e62f551851 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/enums/components.ts +++ b/npm/ng-packs/packages/theme-basic/src/lib/enums/components.ts @@ -5,4 +5,6 @@ export const enum eThemeBasicComponents { Logo = 'Theme.LogoComponent', Routes = 'Theme.RoutesComponent', NavItems = 'Theme.NavItemsComponent', + CurrentUser = 'Theme.CurrentUserComponent', + Languages = 'Theme.LanguagesComponent', } From 5693a05b9fe91bacedbc0bc534dda62fe9291466 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Thu, 18 Jun 2020 18:10:27 +0300 Subject: [PATCH 11/13] feat: register current user and languages components to nav-items.service --- .../packages/theme-basic/src/lib/services/index.ts | 1 - .../src/lib/services/initial.service.ts | 14 +++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/npm/ng-packs/packages/theme-basic/src/lib/services/index.ts b/npm/ng-packs/packages/theme-basic/src/lib/services/index.ts index b904c4d663..5fb95808c9 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/services/index.ts +++ b/npm/ng-packs/packages/theme-basic/src/lib/services/index.ts @@ -1,2 +1 @@ export * from './initial.service'; -export * from './layout-state.service'; diff --git a/npm/ng-packs/packages/theme-basic/src/lib/services/initial.service.ts b/npm/ng-packs/packages/theme-basic/src/lib/services/initial.service.ts index c5bc93cbf0..5b02cf158e 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/services/initial.service.ts +++ b/npm/ng-packs/packages/theme-basic/src/lib/services/initial.service.ts @@ -6,10 +6,17 @@ import { ApplicationLayoutComponent } from '../components/application-layout/app import { AccountLayoutComponent } from '../components/account-layout/account-layout.component'; import { EmptyLayoutComponent } from '../components/empty-layout/empty-layout.component'; import { eThemeBasicComponents } from '../enums/components'; +import { NavItemsService } from '@abp/ng.theme.shared'; +import { LanguagesComponent } from '../components/nav-items/languages.component'; +import { CurrentUserComponent } from '../components/nav-items/current-user.component'; @Injectable({ providedIn: 'root' }) export class InitialService { - constructor(private domInsertion: DomInsertionService, private store: Store) { + constructor( + private domInsertion: DomInsertionService, + private navItemsService: NavItemsService, + private store: Store, + ) { this.appendStyle(); this.store.dispatch([ @@ -26,6 +33,11 @@ export class InitialService { component: EmptyLayoutComponent, }), ]); + + this.navItemsService.addItems([ + { id: eThemeBasicComponents.CurrentUser, component: CurrentUserComponent }, + { id: eThemeBasicComponents.Languages, component: LanguagesComponent }, + ]); } appendStyle() { From 145e302f72058548a469aee376c67ab9e64b28a4 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Tue, 23 Jun 2020 01:39:36 +0300 Subject: [PATCH 12/13] chore: remove an index.ts --- npm/ng-packs/packages/theme-basic/src/lib/services/index.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 npm/ng-packs/packages/theme-basic/src/lib/services/index.ts diff --git a/npm/ng-packs/packages/theme-basic/src/lib/services/index.ts b/npm/ng-packs/packages/theme-basic/src/lib/services/index.ts deleted file mode 100644 index e69de29bb2..0000000000 From cb3b7593bec5699b24d2fad37436f66825814620 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Tue, 23 Jun 2020 07:12:27 +0300 Subject: [PATCH 13/13] feat(theme-basic): add the nav-item.provider --- .../theme-basic/src/lib/providers/index.ts | 1 + .../src/lib/providers/nav-item.provider.ts | 31 +++++++++++++++++++ .../theme-basic/src/lib/theme-basic.module.ts | 5 +-- 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 npm/ng-packs/packages/theme-basic/src/lib/providers/nav-item.provider.ts diff --git a/npm/ng-packs/packages/theme-basic/src/lib/providers/index.ts b/npm/ng-packs/packages/theme-basic/src/lib/providers/index.ts index 607efd62a5..8102d94f62 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/providers/index.ts +++ b/npm/ng-packs/packages/theme-basic/src/lib/providers/index.ts @@ -1 +1,2 @@ +export * from './nav-item.provider'; export * from './styles.provider'; diff --git a/npm/ng-packs/packages/theme-basic/src/lib/providers/nav-item.provider.ts b/npm/ng-packs/packages/theme-basic/src/lib/providers/nav-item.provider.ts new file mode 100644 index 0000000000..f5eca00f04 --- /dev/null +++ b/npm/ng-packs/packages/theme-basic/src/lib/providers/nav-item.provider.ts @@ -0,0 +1,31 @@ +import { NavItemsService } from '@abp/ng.theme.shared'; +import { APP_INITIALIZER } from '@angular/core'; +import { CurrentUserComponent } from '../components/nav-items/current-user.component'; +import { LanguagesComponent } from '../components/nav-items/languages.component'; +import { eThemeBasicComponents } from '../enums/components'; + +export const BASIC_THEME_NAV_ITEM_PROVIDERS = [ + { + provide: APP_INITIALIZER, + useFactory: configureNavItems, + deps: [NavItemsService], + multi: true, + }, +]; + +export function configureNavItems(navItems: NavItemsService) { + return () => { + navItems.addItems([ + { + id: eThemeBasicComponents.Languages, + order: 100, + component: LanguagesComponent, + }, + { + id: eThemeBasicComponents.CurrentUser, + order: 101, + component: CurrentUserComponent, + }, + ]); + }; +} diff --git a/npm/ng-packs/packages/theme-basic/src/lib/theme-basic.module.ts b/npm/ng-packs/packages/theme-basic/src/lib/theme-basic.module.ts index 40362ab5e0..f599124e83 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/theme-basic.module.ts +++ b/npm/ng-packs/packages/theme-basic/src/lib/theme-basic.module.ts @@ -13,6 +13,7 @@ import { ValidationErrorComponent } from './components/validation-error/validati import { CurrentUserComponent } from './components/nav-items/current-user.component'; import { LanguagesComponent } from './components/nav-items/languages.component'; import { BASIC_THEME_STYLES_PROVIDERS } from './providers/styles.provider'; +import { BASIC_THEME_NAV_ITEM_PROVIDERS } from './providers/nav-item.provider'; export const LAYOUTS = [ApplicationLayoutComponent, AccountLayoutComponent, EmptyLayoutComponent]; @@ -62,13 +63,13 @@ export const LAYOUTS = [ApplicationLayoutComponent, AccountLayoutComponent, Empt errorTemplate: ValidationErrorComponent, }), ], - entryComponents: [...LAYOUTS, ValidationErrorComponent], + entryComponents: [...LAYOUTS, ValidationErrorComponent, CurrentUserComponent, LanguagesComponent], }) export class ThemeBasicModule { static forRoot(): ModuleWithProviders { return { ngModule: ThemeBasicModule, - providers: [BASIC_THEME_STYLES_PROVIDERS], + providers: [BASIC_THEME_NAV_ITEM_PROVIDERS, BASIC_THEME_STYLES_PROVIDERS], }; } }