Browse Source

feat: implement session-state.service

pull/6156/head
mehmet-erim 6 years ago
parent
commit
8c7b1fa8fb
  1. 17
      npm/ng-packs/packages/core/src/lib/pipes/localization.pipe.ts
  2. 9
      npm/ng-packs/packages/core/src/lib/services/application-configuration.service.ts
  3. 23
      npm/ng-packs/packages/core/src/lib/services/auth.service.ts
  4. 1
      npm/ng-packs/packages/core/src/lib/services/index.ts
  5. 13
      npm/ng-packs/packages/core/src/lib/services/permission.service.ts
  6. 2
      npm/ng-packs/packages/core/src/lib/services/replaceable-components.service.ts
  7. 5
      npm/ng-packs/packages/core/src/lib/services/rest.service.ts
  8. 10
      npm/ng-packs/packages/core/src/lib/services/routes.service.ts
  9. 25
      npm/ng-packs/packages/core/src/lib/services/session-state.service.ts
  10. 21
      npm/ng-packs/packages/core/src/lib/strategies/auth-flow.strategy.ts
  11. 28
      npm/ng-packs/packages/core/src/lib/utils/environment-utils.ts
  12. 27
      npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts
  13. 25
      npm/ng-packs/packages/core/src/lib/utils/multi-tenancy-utils.ts
  14. 11
      npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.ts
  15. 22
      npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts
  16. 14
      npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.ts
  17. 16
      npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/languages.component.ts
  18. 85
      npm/ng-packs/packages/theme-shared/extensions/src/lib/utils/state.util.ts
  19. 9
      npm/ng-packs/packages/theme-shared/src/lib/utils/date-parser-formatter.ts

17
npm/ng-packs/packages/core/src/lib/pipes/localization.pipe.ts

@ -1,26 +1,23 @@
import { Injectable, Pipe, PipeTransform } from '@angular/core';
import { Store } from '@ngxs/store';
import { Config } from '../models';
import { ConfigState } from '../states';
import { LocalizationService } from '../services/localization.service';
@Injectable()
@Pipe({
name: 'abpLocalization',
})
export class LocalizationPipe implements PipeTransform {
constructor(private store: Store) {}
constructor(private localization: LocalizationService) {}
transform(
value: string | Config.LocalizationWithDefault = '',
...interpolateParams: string[]
): string {
return this.store.selectSnapshot(
ConfigState.getLocalization(
value,
...interpolateParams.reduce(
(acc, val) => (Array.isArray(val) ? [...acc, ...val] : [...acc, val]),
[],
),
return this.localization.instant(
value,
...interpolateParams.reduce(
(acc, val) => (Array.isArray(val) ? [...acc, ...val] : [...acc, val]),
[],
),
);
}

9
npm/ng-packs/packages/core/src/lib/services/application-configuration.service.ts

@ -1,20 +1,19 @@
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Rest } from '../models/rest';
import { ApplicationConfiguration } from '../models/application-configuration';
import { Rest } from '../models/rest';
import { EnvironmentService } from './environment.service';
import { RestService } from './rest.service';
import { Store } from '@ngxs/store';
import { ConfigState } from '../states/config.state';
@Injectable({
providedIn: 'root',
})
export class ApplicationConfigurationService {
get apiName(): string {
return this.store.selectSnapshot(ConfigState.getDeep('environment.application.name'));
return this.environment.getEnvironment().application?.name;
}
constructor(private rest: RestService, private store: Store) {}
constructor(private rest: RestService, private environment: EnvironmentService) {}
getConfiguration(): Observable<ApplicationConfiguration.Response> {
const request: Rest.Request<null> = {

23
npm/ng-packs/packages/core/src/lib/services/auth.service.ts

@ -1,15 +1,15 @@
import { HttpHeaders } from '@angular/common/http';
import { Inject, Injectable, Injector, Optional } from '@angular/core';
import { Navigate } from '@ngxs/router-plugin';
import { Actions, ofActionSuccessful, Store } from '@ngxs/store';
import { Store } from '@ngxs/store';
import { OAuthService } from 'angular-oauth2-oidc';
import { from, Observable } from 'rxjs';
import { switchMap, take, tap } from 'rxjs/operators';
import snq from 'snq';
import { GetAppConfiguration, SetEnvironment } from '../actions/config.actions';
import { ConfigState } from '../states/config.state';
import { AuthFlowStrategy, AUTH_FLOW_STRATEGY } from '../strategies/auth-flow.strategy';
import { RestService } from './rest.service';
import { ApplicationConfigurationService } from './application-configuration.service';
import { ConfigStateService } from './config-state.service';
import { EnvironmentService } from './environment.service';
import { SessionStateService } from './session-state.service';
@Injectable({
@ -24,12 +24,13 @@ export class AuthService {
}
constructor(
private actions: Actions,
private environment: EnvironmentService,
private injector: Injector,
private rest: RestService,
private oAuthService: OAuthService,
private store: Store,
private sessionState: SessionStateService,
private configState: ConfigStateService,
private appConfigService: ApplicationConfigurationService,
@Optional() @Inject('ACCOUNT_OPTIONS') private options: any,
) {
this.setStrategy();
@ -37,9 +38,7 @@ export class AuthService {
}
private setStrategy = () => {
const flow =
this.store.selectSnapshot(ConfigState.getDeep('environment.oAuthConfig.responseType')) ||
'password';
const flow = this.environment.getEnvironment().oAuthConfig.responseType || 'password';
if (this.flow === flow) return;
if (this.strategy) this.strategy.destroy();
@ -52,7 +51,7 @@ export class AuthService {
};
private listenToSetEnvironment() {
this.actions.pipe(ofActionSuccessful(SetEnvironment)).subscribe(this.setStrategy);
this.environment.onUpdate$(state => state.oAuthConfig).subscribe(this.setStrategy);
}
login(username: string, password: string): Observable<any> {
@ -65,7 +64,9 @@ export class AuthService {
new HttpHeaders({ ...(tenant && tenant.id && { __tenant: tenant.id }) }),
),
).pipe(
switchMap(() => this.store.dispatch(new GetAppConfiguration())),
switchMap(() =>
this.appConfigService.getConfiguration().pipe(tap(res => this.configState.setState(res))),
),
tap(() => {
const redirectUrl =
snq(() => window.history.state.redirectUrl) || (this.options || {}).redirectUrl || '/';

1
npm/ng-packs/packages/core/src/lib/services/index.ts

@ -3,6 +3,7 @@ export * from './auth.service';
export * from './config-state.service';
export * from './content-projection.service';
export * from './dom-insertion.service';
export * from './environment.service';
export * from './lazy-load.service';
export * from './list.service';
export * from './localization.service';

13
npm/ng-packs/packages/core/src/lib/services/permission.service.ts

@ -1,13 +1,12 @@
import { ConfigState } from '../states';
import { Store } from '@ngxs/store';
import { Injectable } from '@angular/core';
import { map } from 'rxjs/operators';
import { ApplicationConfiguration } from '../models/application-configuration';
import snq from 'snq';
import { Injectable } from '@angular/core';
import { ApplicationConfiguration } from '../models/application-configuration';
import { ConfigStateService } from './config-state.service';
@Injectable({ providedIn: 'root' })
export class PermissionService {
constructor(private store: Store) {}
constructor(private configState: ConfigStateService) {}
getGrantedPolicy$(key: string) {
return this.getStream().pipe(map(policies => this.isPolicyGranted(key, policies)));
@ -43,11 +42,11 @@ export class PermissionService {
}
private getStream() {
return this.store.select(ConfigState).pipe(map(this.mapToPolicies));
return this.configState.getAll$().pipe(map(this.mapToPolicies));
}
private getSnapshot() {
return this.mapToPolicies(this.store.selectSnapshot(ConfigState));
return this.mapToPolicies(this.configState.getAll());
}
private mapToPolicies(applicationConfiguration: ApplicationConfiguration.Response) {

2
npm/ng-packs/packages/core/src/lib/services/replaceable-components.service.ts

@ -8,7 +8,7 @@ import { reloadRoute } from '../utils/route-utils';
@Injectable({ providedIn: 'root' })
export class ReplaceableComponentsService {
private store: InternalStore<ReplaceableComponents.ReplaceableComponent[]>;
private readonly store: InternalStore<ReplaceableComponents.ReplaceableComponent[]>;
get replaceableComponents$(): Observable<ReplaceableComponents.ReplaceableComponent[]> {
return this.store.sliceState(state => state);

5
npm/ng-packs/packages/core/src/lib/services/rest.service.ts

@ -5,10 +5,10 @@ import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { RestOccurError } from '../actions/rest.actions';
import { Rest } from '../models/rest';
import { ConfigState } from '../states/config.state';
import { isUndefinedOrEmptyString } from '../utils/common-utils';
import { ABP } from '../models/common';
import { CORE_OPTIONS } from '../tokens/options.token';
import { EnvironmentService } from './environment.service';
@Injectable({
providedIn: 'root',
@ -18,10 +18,11 @@ export class RestService {
@Inject(CORE_OPTIONS) private options: ABP.Root,
private http: HttpClient,
private store: Store,
private environment: EnvironmentService,
) {}
private getApiFromStore(apiName: string): string {
return this.store.selectSnapshot(ConfigState.getApiUrl(apiName));
return this.environment.getApiUrl(apiName);
}
handleError(err: any): Observable<any> {

10
npm/ng-packs/packages/core/src/lib/services/routes.service.ts

@ -1,10 +1,10 @@
import { Injectable, Injector, OnDestroy } from '@angular/core';
import { Actions, ofActionSuccessful } from '@ngxs/store';
import { Actions } from '@ngxs/store';
import { BehaviorSubject, Observable, Subscription } from 'rxjs';
import { GetAppConfiguration } from '../actions/config.actions';
import { ABP } from '../models/common';
import { pushValueTo } from '../utils/array-utils';
import { BaseTreeNode, createTreeFromList, TreeNode } from '../utils/tree-utils';
import { ConfigStateService } from './config-state.service';
import { PermissionService } from './permission.service';
export abstract class AbstractTreeService<T extends object> {
@ -152,10 +152,8 @@ export abstract class AbstractNavTreeService<T extends ABP.Nav>
constructor(protected injector: Injector) {
super();
this.actions = injector.get(Actions);
this.subscription = this.actions
.pipe(ofActionSuccessful(GetAppConfiguration))
.subscribe(() => this.refresh());
const configState = this.injector.get(ConfigStateService);
this.subscription = configState.onUpdate$(state => state).subscribe(() => this.refresh());
this.permissionService = injector.get(PermissionService);
}

25
npm/ng-packs/packages/core/src/lib/services/session-state.service.ts

@ -3,6 +3,8 @@ import { ApplicationConfiguration } from '../models/application-configuration';
import { Session } from '../models/session';
import { InternalStore } from '../utils/internal-store-utils';
import compare from 'just-compare';
import { ConfigStateService } from './config-state.service';
import { filter, take, tap } from 'rxjs/operators';
export interface SessionDetail {
openedTabCount: number;
@ -20,8 +22,9 @@ export class SessionStateService {
localStorage.setItem('abpSession', JSON.stringify(this.store.state));
};
constructor() {
constructor(private configState: ConfigStateService) {
this.init();
this.setInitialLanguage();
}
private init() {
@ -33,6 +36,25 @@ export class SessionStateService {
this.store.sliceUpdate(state => state).subscribe(this.updateLocalStorage);
}
private setInitialLanguage() {
if (this.getLanguage()) return;
this.configState
.getDeep$('localization.currentCulture.cultureName')
.pipe(
tap(console.warn),
filter(cultureName => !!cultureName),
take(1),
)
.subscribe(lang => {
if (lang.includes(';')) {
lang = lang.split(';')[0];
}
this.setLanguage(lang);
});
}
onLanguageChange$() {
return this.store.sliceUpdate(state => state.language);
}
@ -67,5 +89,6 @@ export class SessionStateService {
if (language === this.store.state.language) return;
this.store.patch({ language });
document.documentElement.setAttribute('lang', language);
}
}

21
npm/ng-packs/packages/core/src/lib/strategies/auth-flow.strategy.ts

@ -4,10 +4,11 @@ import { Store } from '@ngxs/store';
import { AuthConfig, OAuthService, OAuthStorage } from 'angular-oauth2-oidc';
import { Observable, of } from 'rxjs';
import { switchMap, tap } from 'rxjs/operators';
import { GetAppConfiguration } from '../actions/config.actions';
import { RestOccurError } from '../actions/rest.actions';
import { ApplicationConfigurationService } from '../services/application-configuration.service';
import { ConfigStateService } from '../services/config-state.service';
import { EnvironmentService } from '../services/environment.service';
import { RestService } from '../services/rest.service';
import { ConfigState } from '../states/config.state';
export const oAuthStorage = localStorage;
@ -15,6 +16,9 @@ export abstract class AuthFlowStrategy {
abstract readonly isInternalAuth: boolean;
protected store: Store;
protected environment: EnvironmentService;
protected configState: ConfigStateService;
protected appConfigService: ApplicationConfigurationService;
protected oAuthService: OAuthService;
protected oAuthConfig: AuthConfig;
abstract checkIfInternalAuth(): boolean;
@ -26,13 +30,16 @@ export abstract class AuthFlowStrategy {
constructor(protected injector: Injector) {
this.store = injector.get(Store);
this.environment = injector.get(EnvironmentService);
this.configState = injector.get(ConfigStateService);
this.appConfigService = injector.get(ApplicationConfigurationService);
this.oAuthService = injector.get(OAuthService);
this.oAuthConfig = this.store.selectSnapshot(ConfigState.getDeep('environment.oAuthConfig'));
this.oAuthConfig = this.environment.getEnvironment().oAuthConfig;
}
async init(): Promise<any> {
const shouldClear = shouldStorageClear(
this.store.selectSnapshot(ConfigState.getDeep('environment.oAuthConfig.clientId')),
this.environment.getEnvironment().oAuthConfig.clientId,
oAuthStorage,
);
if (shouldClear) clearOAuthStorage(oAuthStorage);
@ -91,7 +98,7 @@ export class AuthPasswordFlowStrategy extends AuthFlowStrategy {
logout() {
const rest = this.injector.get(RestService);
const issuer = this.store.selectSnapshot(ConfigState.getDeep('environment.oAuthConfig.issuer'));
const issuer = this.environment.getEnvironment().oAuthConfig.issuer;
return rest
.request(
{
@ -103,7 +110,9 @@ export class AuthPasswordFlowStrategy extends AuthFlowStrategy {
)
.pipe(
tap(() => this.oAuthService.logOut()),
switchMap(() => this.store.dispatch(new GetAppConfiguration())),
switchMap(() =>
this.appConfigService.getConfiguration().pipe(tap(res => this.configState.setState(res))),
),
);
}

28
npm/ng-packs/packages/core/src/lib/utils/environment-utils.ts

@ -1,42 +1,44 @@
import { HttpClient } from '@angular/common/http';
import { Injector } from '@angular/core';
import { Store } from '@ngxs/store';
import { catchError, switchMap } from 'rxjs/operators';
import { SetEnvironment } from '../actions/config.actions';
import { Config } from '../models/config';
import { catchError, tap } from 'rxjs/operators';
import { RestOccurError } from '../actions/rest.actions';
import { Environment, RemoteEnv } from '../models/environment';
import { EnvironmentService } from '../services/environment.service';
import { deepMerge } from './object-utils';
export function getRemoteEnv(injector: Injector, environment: Partial<Config.Environment>) {
export function getRemoteEnv(injector: Injector, environment: Partial<Environment>) {
const environmentService = injector.get(EnvironmentService);
const { remoteEnv } = environment;
const { headers = {}, method = 'GET', url } = remoteEnv || ({} as Config.RemoteEnv);
const { headers = {}, method = 'GET', url } = remoteEnv || ({} as RemoteEnv);
if (!url) return Promise.resolve();
const http = injector.get(HttpClient);
const store = injector.get(Store);
return http
.request<Config.Environment>(method, url, { headers })
.request<Environment>(method, url, { headers })
.pipe(
catchError(err => store.dispatch(new RestOccurError(err))), // TODO: Condiser get handle function from a provider
switchMap(env => store.dispatch(mergeEnvironments(environment, env, remoteEnv))),
tap(env => environmentService.setState(mergeEnvironments(environment, env, remoteEnv))),
)
.toPromise();
}
function mergeEnvironments(
local: Partial<Config.Environment>,
local: Partial<Environment>,
remote: any,
config: Config.RemoteEnv,
) {
config: RemoteEnv,
): Environment {
switch (config.mergeStrategy) {
case 'deepmerge':
return new SetEnvironment(deepMerge(local, remote));
return deepMerge(local, remote);
case 'overwrite':
case null:
case undefined:
return new SetEnvironment(remote);
return remote;
default:
return new SetEnvironment(config.mergeStrategy(local, remote));
return config.mergeStrategy(local, remote);
}
}

27
npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts

@ -3,12 +3,14 @@ import { Injector } from '@angular/core';
import { Store } from '@ngxs/store';
import { OAuthService } from 'angular-oauth2-oidc';
import { tap } from 'rxjs/operators';
import { GetAppConfiguration } from '../actions/config.actions';
import { ApplicationConfiguration } from '../models/application-configuration';
import { ABP } from '../models/common';
import { Environment } from '../models/environment';
import { ApplicationConfigurationService } from '../services/application-configuration.service';
import { AuthService } from '../services/auth.service';
import { ConfigStateService } from '../services/config-state.service';
import { EnvironmentService } from '../services/environment.service';
import { SessionStateService } from '../services/session-state.service';
import { ConfigState } from '../states/config.state';
import { clearOAuthStorage } from '../strategies/auth-flow.strategy';
import { CORE_OPTIONS } from '../tokens/options.token';
import { getRemoteEnv } from './environment-utils';
@ -16,22 +18,26 @@ import { parseTenantFromUrl } from './multi-tenancy-utils';
export function getInitialData(injector: Injector) {
const fn = async () => {
const store: Store = injector.get(Store);
const environmentService = injector.get(EnvironmentService);
const configState = injector.get(ConfigStateService);
const appConfigService = injector.get(ApplicationConfigurationService);
const options = injector.get(CORE_OPTIONS) as ABP.Root;
environmentService.setState(options.environment as Environment);
await getRemoteEnv(injector, options.environment);
await parseTenantFromUrl(injector);
await injector.get(AuthService).init();
if (options.skipGetAppConfiguration) return;
return store
.dispatch(new GetAppConfiguration())
return appConfigService
.getConfiguration()
.pipe(
tap(() => checkAccessToken(store, injector)),
tap(res => configState.setState(res)),
tap(() => checkAccessToken(injector)),
tap(() => {
const currentTenant = store.selectSnapshot(
ConfigState.getDeep('currentTenant'),
const currentTenant = configState.getOne(
'currentTenant',
) as ApplicationConfiguration.CurrentTenant;
if (!currentTenant?.id) return;
@ -44,9 +50,10 @@ export function getInitialData(injector: Injector) {
return fn;
}
export function checkAccessToken(store: Store, injector: Injector) {
export function checkAccessToken(injector: Injector) {
const configState = injector.get(ConfigStateService);
const oAuth = injector.get(OAuthService);
if (oAuth.hasValidAccessToken() && !store.selectSnapshot(ConfigState.getDeep('currentUser.id'))) {
if (oAuth.hasValidAccessToken() && !configState.getDeep('currentUser.id')) {
clearOAuthStorage();
}
}

25
npm/ng-packs/packages/core/src/lib/utils/multi-tenancy-utils.ts

@ -1,11 +1,10 @@
import { Injector } from '@angular/core';
import { Store } from '@ngxs/store';
import clone from 'just-clone';
import { of } from 'rxjs';
import { switchMap, tap } from 'rxjs/operators';
import { SetEnvironment } from '../actions';
import { Config } from '../models/config';
import { Environment } from '../models/environment';
import { EnvironmentService } from '../services/environment.service';
import { MultiTenancyService } from '../services/multi-tenancy.service';
import { ConfigState } from '../states/config.state';
import { createTokenParser } from './string-utils';
const tenancyPlaceholder = '{0}';
@ -19,17 +18,17 @@ function getCurrentTenancyName(appBaseUrl: string): string {
}
export async function parseTenantFromUrl(injector: Injector) {
const store: Store = injector.get(Store);
const environmentService = injector.get(EnvironmentService);
const multiTenancyService = injector.get(MultiTenancyService);
const environment = store.selectSnapshot(ConfigState.getOne('environment')) as Config.Environment;
const { baseUrl = '' } = environment.application;
const baseUrl = environmentService.getEnvironment()?.application?.baseUrl || '';
const tenancyName = getCurrentTenancyName(baseUrl);
if (tenancyName) {
multiTenancyService.isTenantBoxVisible = false;
setEnvironment(injector, tenancyName);
return setEnvironment(store, tenancyName)
return of(null)
.pipe(
switchMap(() => multiTenancyService.findTenantByName(tenancyName, { __tenant: '' })),
tap(res => {
@ -44,10 +43,10 @@ export async function parseTenantFromUrl(injector: Injector) {
return Promise.resolve();
}
function setEnvironment(store: Store, tenancyName: string) {
const environment = clone(
store.selectSnapshot(ConfigState.getOne('environment')),
) as Config.Environment;
function setEnvironment(injector: Injector, tenancyName: string) {
const environmentService = injector.get(EnvironmentService);
const environment = clone(environmentService.getEnvironment()) as Environment;
if (environment.application.baseUrl) {
environment.application.baseUrl = environment.application.baseUrl.replace(
@ -70,5 +69,5 @@ function setEnvironment(store: Store, tenancyName: string) {
});
});
return store.dispatch(new SetEnvironment(environment));
return environmentService.setState(environment);
}

11
npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.ts

@ -1,8 +1,8 @@
import { TrackByService, GetAppConfiguration } from '@abp/ng.core';
import { ApplicationConfigurationService, ConfigStateService, TrackByService } from '@abp/ng.core';
import { LocaleDirection } from '@abp/ng.theme.shared';
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { Store } from '@ngxs/store';
import { finalize } from 'rxjs/operators';
import { finalize, tap } from 'rxjs/operators';
import { FeatureManagement } from '../../models/feature-management';
import { FeaturesService } from '../../proxy/feature-management/features.service';
import {
@ -65,6 +65,8 @@ export class FeatureManagementComponent
public readonly track: TrackByService,
protected service: FeaturesService,
protected store: Store,
protected configState: ConfigStateService,
protected appConfigService: ApplicationConfigurationService,
) {}
openModal() {
@ -115,7 +117,10 @@ export class FeatureManagementComponent
if (!this.providerKey) {
// to refresh host's features
this.store.dispatch(new GetAppConfiguration());
this.appConfigService
.getConfiguration()
.pipe(tap(res => this.configState.setState(res)))
.subscribe();
}
});
}

22
npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts

@ -1,4 +1,8 @@
import { ApplicationConfiguration, ConfigState, GetAppConfiguration } from '@abp/ng.core';
import {
ApplicationConfiguration,
ApplicationConfigurationService,
ConfigStateService,
} from '@abp/ng.core';
import { LocaleDirection } from '@abp/ng.theme.shared';
import { Component, EventEmitter, Input, Output, Renderer2, TrackByFunction } from '@angular/core';
import { Select, Store } from '@ngxs/store';
@ -105,7 +109,11 @@ export class PermissionManagementComponent
);
}
constructor(private store: Store, private renderer: Renderer2) {}
constructor(
protected store: Store,
protected configState: ConfigStateService,
protected appConfigService: ApplicationConfigurationService,
) {}
getChecked(name: string) {
return (this.permissions.find(per => per.name === name) || { isGranted: false }).isGranted;
@ -239,7 +247,11 @@ export class PermissionManagementComponent
)
.pipe(
switchMap(() =>
this.shouldFetchAppConfig() ? this.store.dispatch(GetAppConfiguration) : of(null),
this.shouldFetchAppConfig()
? this.appConfigService
.getConfiguration()
.pipe(tap(res => this.configState.setState(res)))
: of(null),
),
finalize(() => (this.modalBusy = false)),
)
@ -282,8 +294,8 @@ export class PermissionManagementComponent
}
shouldFetchAppConfig() {
const currentUser = this.store.selectSnapshot(
ConfigState.getOne('currentUser'),
const currentUser = this.configState.getOne(
'currentUser',
) as ApplicationConfiguration.CurrentUser;
if (this.providerName === 'R') return currentUser.roles.some(role => role === this.providerKey);

14
npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/current-user.component.ts

@ -1,7 +1,6 @@
import { ApplicationConfiguration, ConfigState, AuthService } from '@abp/ng.core';
import { ApplicationConfiguration, AuthService, ConfigStateService } 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({
@ -48,14 +47,19 @@ import { Observable } from 'rxjs';
`,
})
export class CurrentUserComponent implements OnInit {
@Select(ConfigState.getOne('currentUser'))
currentUser$: Observable<ApplicationConfiguration.CurrentUser>;
currentUser$: Observable<ApplicationConfiguration.CurrentUser> = this.configState.getOne$(
'currentUser',
);
get smallScreen(): boolean {
return window.innerWidth < 992;
}
constructor(private authService: AuthService, private router: Router) {}
constructor(
private authService: AuthService,
private router: Router,
private configState: ConfigStateService,
) {}
ngOnInit() {}

16
npm/ng-packs/packages/theme-basic/src/lib/components/nav-items/languages.component.ts

@ -1,6 +1,5 @@
import { ApplicationConfiguration, ConfigState, SessionStateService } from '@abp/ng.core';
import { Component, OnInit } from '@angular/core';
import { Select } from '@ngxs/store';
import { ApplicationConfiguration, ConfigStateService, SessionStateService } from '@abp/ng.core';
import { Component } from '@angular/core';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import snq from 'snq';
@ -44,13 +43,14 @@ import snq from 'snq';
</div>
`,
})
export class LanguagesComponent implements OnInit {
export class LanguagesComponent {
get smallScreen(): boolean {
return window.innerWidth < 992;
}
@Select(ConfigState.getDeep('localization.languages'))
languages$: Observable<ApplicationConfiguration.Language[]>;
languages$: Observable<ApplicationConfiguration.Language[]> = this.configState.getDeep$(
'localization.languages',
);
get defaultLanguage$(): Observable<string> {
return this.languages$.pipe(
@ -78,9 +78,7 @@ export class LanguagesComponent implements OnInit {
return this.sessionState.getLanguage();
}
constructor(private sessionState: SessionStateService) {}
ngOnInit() {}
constructor(private sessionState: SessionStateService, private configState: ConfigStateService) {}
onChangeLang(cultureName: string) {
this.sessionState.setLanguage(cultureName);

85
npm/ng-packs/packages/theme-shared/extensions/src/lib/utils/state.util.ts

@ -1,5 +1,4 @@
import { ABP, ApplicationConfiguration } from '@abp/ng.core';
import { createSelector, Store } from '@ngxs/store';
import { ABP, ApplicationConfiguration, ConfigStateService } from '@abp/ng.core';
import { Observable, pipe, zip } from 'rxjs';
import { filter, map, switchMap, take } from 'rxjs/operators';
import { ePropType } from '../enums/props.enum';
@ -12,51 +11,59 @@ import { createDisplayNameLocalizationPipeKeyGenerator } from './localization.ut
import { createExtraPropertyValueResolver } from './props.util';
import { getValidatorsFromProperty } from './validation.util';
const selectConfig = (state: any) => state.ConfigState;
const selectObjectExtensions = createSelector(
[selectConfig],
(config: ObjectExtensions.Config) => config.objectExtensions,
);
const selectLocalization = createSelector(
[selectConfig],
(config: ApplicationConfiguration.Response) => config.localization,
);
const selectEnums = createSelector(
[selectObjectExtensions, selectLocalization],
(extensions: ObjectExtensions.Item) =>
Object.keys(extensions.enums).reduce((acc, key) => {
const { fields, localizationResource } = extensions.enums[key];
acc[key] = {
fields,
localizationResource,
transformed: createEnum(fields),
};
return acc;
}, {} as ObjectExtensions.Enums),
);
const createObjectExtensionEntitiesSelector = (moduleKey: ModuleKey) =>
createSelector([selectObjectExtensions], (extensions: ObjectExtensions.Item) => {
if (!extensions) return null;
return (extensions.modules[moduleKey] || ({} as ObjectExtensions.Module)).entities;
});
export function getObjectExtensionEntitiesFromStore(store: Store, moduleKey: ModuleKey) {
return store.select(createObjectExtensionEntitiesSelector(moduleKey)).pipe(
function selectObjectExtensions(
configState: ConfigStateService,
): Observable<ObjectExtensions.Item> {
return configState.getOne$('objectExtensions');
}
function selectLocalization(
configState: ConfigStateService,
): Observable<ApplicationConfiguration.Localization> {
return configState.getOne$('localization');
}
function selectEnums(
configState: ConfigStateService,
): Observable<Record<string, ObjectExtensions.Enum>> {
return selectObjectExtensions(configState).pipe(
map((extensions: ObjectExtensions.Item) =>
Object.keys(extensions.enums).reduce((acc, key) => {
const { fields, localizationResource } = extensions.enums[key];
acc[key] = {
fields,
localizationResource,
transformed: createEnum(fields),
};
return acc;
}, {} as ObjectExtensions.Enums),
),
);
}
export function getObjectExtensionEntitiesFromStore(
configState: ConfigStateService,
moduleKey: ModuleKey,
) {
return selectObjectExtensions(configState).pipe(
map(extensions => {
if (!extensions) return null;
return (extensions.modules[moduleKey] || ({} as ObjectExtensions.Module)).entities;
}),
map(entities => (isUndefined(entities) ? {} : entities)),
filter<ObjectExtensions.Entities>(Boolean),
take(1),
);
}
export function mapEntitiesToContributors<T = any>(store: Store, resource: string) {
export function mapEntitiesToContributors<T = any>(
configState: ConfigStateService,
resource: string,
) {
return pipe(
switchMap(entities =>
zip(store.select(selectLocalization), store.select(selectEnums)).pipe(
zip(selectLocalization(configState), selectEnums(configState)).pipe(
map(([localization, enums]) => {
const generateDisplayName = createDisplayNameLocalizationPipeKeyGenerator(localization);

9
npm/ng-packs/packages/theme-shared/src/lib/utils/date-parser-formatter.ts

@ -1,8 +1,7 @@
import { ApplicationConfiguration, ConfigState } from '@abp/ng.core';
import { ApplicationConfiguration, ConfigStateService } from '@abp/ng.core';
import { DatePipe } from '@angular/common';
import { Injectable, Optional } from '@angular/core';
import { NgbDateParserFormatter, NgbDateStruct } from '@ng-bootstrap/ng-bootstrap';
import { Store } from '@ngxs/store';
function padNumber(value: number) {
if (isNumber(value)) {
@ -22,7 +21,7 @@ function toInteger(value: any): number {
@Injectable()
export class DateParserFormatter extends NgbDateParserFormatter {
constructor(@Optional() private datePipe: DatePipe, private store: Store) {
constructor(@Optional() private datePipe: DatePipe, private configState: ConfigStateService) {
super();
}
@ -50,8 +49,8 @@ export class DateParserFormatter extends NgbDateParserFormatter {
}
format(date: NgbDateStruct): string {
const { shortDatePattern } = (this.store.selectSnapshot(
ConfigState.getOne('localization'),
const { shortDatePattern } = (this.configState.getOne(
'localization',
) as ApplicationConfiguration.Localization).currentCulture.dateTimeFormat;
if (date && this.datePipe) {

Loading…
Cancel
Save