From 24e727ec4a6e5049c7eda277e4e4ec413c610a14 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Thu, 18 Jun 2020 18:07:00 +0300 Subject: [PATCH 001/110] 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 002/110] 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 003/110] 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 004/110] 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 005/110] 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 006/110] 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 007/110] 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 008/110] 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 009/110] 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 010/110] 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 011/110] 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 7634aaf74be9458ecf10c8609ba63903c3684523 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Fri, 19 Jun 2020 10:27:53 +0300 Subject: [PATCH 012/110] feat: add route.provider to dev-app --- .../apps/dev-app/src/app/app.module.ts | 2 ++ .../apps/dev-app/src/app/route.provider.ts | 20 +++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 npm/ng-packs/apps/dev-app/src/app/route.provider.ts diff --git a/npm/ng-packs/apps/dev-app/src/app/app.module.ts b/npm/ng-packs/apps/dev-app/src/app/app.module.ts index acf8fcaaa8..7c9e2781e2 100644 --- a/npm/ng-packs/apps/dev-app/src/app/app.module.ts +++ b/npm/ng-packs/apps/dev-app/src/app/app.module.ts @@ -13,6 +13,7 @@ import { environment } from '../environments/environment'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { SharedModule } from './shared/shared.module'; +import { APP_ROUTE_PROVIDER } from './route.provider'; const LOGGERS = [NgxsLoggerPluginModule.forRoot({ disabled: false })]; @@ -35,6 +36,7 @@ const LOGGERS = [NgxsLoggerPluginModule.forRoot({ disabled: false })]; SharedModule, ...(environment.production ? [] : LOGGERS), ], + providers: [APP_ROUTE_PROVIDER], declarations: [AppComponent], bootstrap: [AppComponent], }) diff --git a/npm/ng-packs/apps/dev-app/src/app/route.provider.ts b/npm/ng-packs/apps/dev-app/src/app/route.provider.ts new file mode 100644 index 0000000000..5a14ad7ba0 --- /dev/null +++ b/npm/ng-packs/apps/dev-app/src/app/route.provider.ts @@ -0,0 +1,20 @@ +import { RoutesService, eLayoutType } from '@abp/ng.core'; +import { APP_INITIALIZER } from '@angular/core'; + +export const APP_ROUTE_PROVIDER = [ + { provide: APP_INITIALIZER, useFactory: configureRoutes, deps: [RoutesService], multi: true }, +]; + +function configureRoutes(routes: RoutesService) { + return () => { + routes.add([ + { + path: '/', + name: '::Menu:Home', + iconClass: 'fas fa-home', + order: 1, + layout: eLayoutType.application, + }, + ]); + }; +} From 6395a6c65bcacfdfee4fc1b05ddc2697890600e1 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Fri, 19 Jun 2020 10:28:08 +0300 Subject: [PATCH 013/110] chore: remove ApplicationLayoutComponent from home-routing.module --- npm/ng-packs/apps/dev-app/src/app/home/home-routing.module.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/npm/ng-packs/apps/dev-app/src/app/home/home-routing.module.ts b/npm/ng-packs/apps/dev-app/src/app/home/home-routing.module.ts index 367affb583..634706a36c 100644 --- a/npm/ng-packs/apps/dev-app/src/app/home/home-routing.module.ts +++ b/npm/ng-packs/apps/dev-app/src/app/home/home-routing.module.ts @@ -1,12 +1,10 @@ import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { HomeComponent } from './home.component'; -import { ApplicationLayoutComponent } from '@abp/ng.theme.basic'; const routes: Routes = [ { path: '', - component: ApplicationLayoutComponent, children: [{ path: '', component: HomeComponent }], }, ]; From e88d5b4cba80e18a51ffe7bfdf83fdd59fdf04b8 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Fri, 19 Jun 2020 14:21:30 +0300 Subject: [PATCH 014/110] feat: define DynamicLayoutComponent in root level --- .../dev-app/src/app/app-routing.module.ts | 55 ++++++++++--------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/npm/ng-packs/apps/dev-app/src/app/app-routing.module.ts b/npm/ng-packs/apps/dev-app/src/app/app-routing.module.ts index be5089316a..8f6973079d 100644 --- a/npm/ng-packs/apps/dev-app/src/app/app-routing.module.ts +++ b/npm/ng-packs/apps/dev-app/src/app/app-routing.module.ts @@ -1,36 +1,37 @@ -import { ABP } from '@abp/ng.core'; +import { ABP, DynamicLayoutComponent } from '@abp/ng.core'; import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; const routes: Routes = [ { path: '', - loadChildren: () => import('./home/home.module').then(m => m.HomeModule), - data: { - routes: { - name: '::Menu:Home', - order: 1, - } as ABP.Route, - }, - }, - { - path: 'account', - loadChildren: () => - import('@abp/ng.account').then(m => m.AccountModule.forLazy({ redirectUrl: '/' })), - }, - { - path: 'identity', - loadChildren: () => import('@abp/ng.identity').then(m => m.IdentityModule.forLazy()), - }, - { - path: 'tenant-management', - loadChildren: () => - import('@abp/ng.tenant-management').then(m => m.TenantManagementModule.forLazy()), - }, - { - path: 'setting-management', - loadChildren: () => - import('@abp/ng.setting-management').then(m => m.SettingManagementModule.forLazy()), + component: DynamicLayoutComponent, + children: [ + { + path: '', + pathMatch: 'full', + loadChildren: () => import('./home/home.module').then(m => m.HomeModule), + }, + { + path: 'account', + loadChildren: () => + import('@abp/ng.account').then(m => m.AccountModule.forLazy({ redirectUrl: '/' })), + }, + { + path: 'identity', + loadChildren: () => import('@abp/ng.identity').then(m => m.IdentityModule.forLazy()), + }, + { + path: 'tenant-management', + loadChildren: () => + import('@abp/ng.tenant-management').then(m => m.TenantManagementModule.forLazy()), + }, + { + path: 'setting-management', + loadChildren: () => + import('@abp/ng.setting-management').then(m => m.SettingManagementModule.forLazy()), + }, + ], }, ]; From c0896e6806660bf894cf480a4abcd4210cd1b88b Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Fri, 19 Jun 2020 14:22:03 +0300 Subject: [PATCH 015/110] feat: check dynamic layout other instance --- .../core/src/lib/components/dynamic-layout.component.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts b/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts index 5455187086..d2248550d8 100644 --- a/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts +++ b/npm/ng-packs/packages/core/src/lib/components/dynamic-layout.component.ts @@ -1,4 +1,4 @@ -import { Component, Injector, OnDestroy, Type } from '@angular/core'; +import { Component, Injector, OnDestroy, Type, Optional, SkipSelf } from '@angular/core'; import { ActivatedRoute, NavigationEnd, Router } from '@angular/router'; import { Store } from '@ngxs/store'; import { eLayoutType } from '../enums/common'; @@ -28,7 +28,10 @@ export class DynamicLayoutComponent implements OnDestroy { private route: ActivatedRoute, private routes: RoutesService, private store: Store, + @Optional() @SkipSelf() dynamicLayoutComponent: DynamicLayoutComponent, ) { + if (dynamicLayoutComponent) return; + const router = injector.get(Router); const layouts = { application: this.getComponent('Theme.ApplicationLayoutComponent'), From 0508ebabef63c8585b12515c974b1420a63e1407 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Fri, 19 Jun 2020 14:22:19 +0300 Subject: [PATCH 016/110] chore: deprecate visibility.directive --- .../core/src/lib/directives/visibility.directive.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/npm/ng-packs/packages/core/src/lib/directives/visibility.directive.ts b/npm/ng-packs/packages/core/src/lib/directives/visibility.directive.ts index 2dffa1532d..f5f4d22f5e 100644 --- a/npm/ng-packs/packages/core/src/lib/directives/visibility.directive.ts +++ b/npm/ng-packs/packages/core/src/lib/directives/visibility.directive.ts @@ -2,6 +2,10 @@ import { Directive, Input, Optional, ElementRef, Renderer2, AfterViewInit } from import { Subject } from 'rxjs'; import snq from 'snq'; +/** + * + * @deprecated To be deleted in v3.3 + */ @Directive({ selector: '[abpVisibility]', }) @@ -40,7 +44,8 @@ export class VisibilityDirective implements AfterViewInit { setTimeout(() => { const htmlNodes = snq( - () => Array.from(this.focusedElement.childNodes).filter(node => node instanceof HTMLElement), + () => + Array.from(this.focusedElement.childNodes).filter(node => node instanceof HTMLElement), [], ); From c27791e52a4da175c492cb71d675eaf45ef78884 Mon Sep 17 00:00:00 2001 From: mehmet-erim Date: Fri, 19 Jun 2020 14:22:40 +0300 Subject: [PATCH 017/110] feat: add findRequiredPolicy method to routes.component --- .../components/routes/routes.component.html | 5 ++- .../lib/components/routes/routes.component.ts | 35 +++++++++++++++++-- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.html b/npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.html index 4d22ddc8d2..60f2de6c1c 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.html +++ b/npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.html @@ -18,8 +18,8 @@