Browse Source

Merge pull request #2425 from abpframework/feat/add-route-action

feat/add-route-action
pull/2440/head
Mehmet Erim 7 years ago
committed by GitHub
parent
commit
3dbb938e5e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      npm/ng-packs/packages/core/src/lib/actions/config.actions.ts
  2. 19
      npm/ng-packs/packages/core/src/lib/plugins/config.plugin.ts
  3. 158
      npm/ng-packs/packages/core/src/lib/states/config.state.ts
  4. 13
      npm/ng-packs/packages/core/src/lib/tests/config.plugin.spec.ts

8
npm/ng-packs/packages/core/src/lib/actions/config.actions.ts

@ -8,3 +8,11 @@ export class PatchRouteByName {
export class GetAppConfiguration {
static readonly type = '[Config] Get App Configuration';
}
/**
* @see usage: https://github.com/abpframework/abp/pull/2425#issue-355018812
*/
export class AddRoute {
static readonly type = '[Config] Add Route';
constructor(public payload: Omit<ABP.Route, 'children'>) {}
}

19
npm/ng-packs/packages/core/src/lib/plugins/config.plugin.ts

@ -1,6 +1,13 @@
import { Inject, Injectable, InjectionToken } from '@angular/core';
import { Router, Routes } from '@angular/router';
import { actionMatcher, InitState, NgxsNextPluginFn, NgxsPlugin, setValue, UpdateState } from '@ngxs/store';
import {
actionMatcher,
InitState,
NgxsNextPluginFn,
NgxsPlugin,
setValue,
UpdateState,
} from '@ngxs/store';
import snq from 'snq';
import { ABP } from '../models';
import { organizeRoutes, getAbpRoutes } from '../utils/route-utils';
@ -12,7 +19,10 @@ export const NGXS_CONFIG_PLUGIN_OPTIONS = new InjectionToken('NGXS_CONFIG_PLUGIN
export class ConfigPlugin implements NgxsPlugin {
private initialized = false;
constructor(@Inject(NGXS_CONFIG_PLUGIN_OPTIONS) private options: ABP.Root, private router: Router) {}
constructor(
@Inject(NGXS_CONFIG_PLUGIN_OPTIONS) private options: ABP.Root,
private router: Router,
) {}
handle(state: any, event: any, next: NgxsNextPluginFn) {
const matches = actionMatcher(event);
@ -54,7 +64,9 @@ function transformRoutes(routes: Routes = [], wrappers: ABP.FullRoute[] = []): a
routes
.filter(route => route.component || route.loadChildren)
.forEach(route => {
const abpPackage = abpRoutes.find(abp => abp.path.toLowerCase() === route.path.toLowerCase() && !abp.wrapper);
const abpPackage = abpRoutes.find(
abp => abp.path.toLowerCase() === route.path.toLowerCase() && !abp.wrapper,
);
const { length } = transformed;
@ -104,6 +116,7 @@ function flatRoutes(routes: ABP.FullRoute[]): ABP.FullRoute[] {
return r.reduce((acc, val) => {
let value: ABP.FullRoute[] = [val];
if (val.children) {
val.children = val.children.map(child => ({ ...child, parentName: val.name }));
value = [val, ...flat(val.children)];
}

158
npm/ng-packs/packages/core/src/lib/states/config.state.ts

@ -1,18 +1,8 @@
import {
Action,
createSelector,
Selector,
State,
StateContext,
Store,
} from '@ngxs/store';
import { Action, createSelector, Selector, State, StateContext, Store } from '@ngxs/store';
import { of } from 'rxjs';
import { switchMap, tap } from 'rxjs/operators';
import snq from 'snq';
import {
GetAppConfiguration,
PatchRouteByName,
} from '../actions/config.actions';
import { GetAppConfiguration, PatchRouteByName, AddRoute } from '../actions/config.actions';
import { SetLanguage } from '../actions/session.actions';
import { ABP } from '../models/common';
import { Config } from '../models/config';
@ -83,12 +73,9 @@ export class ConfigState {
}
static getApiUrl(key?: string) {
const selector = createSelector(
[ConfigState],
(state: Config.State): string => {
return state.environment.apis[key || 'default'].url;
},
);
const selector = createSelector([ConfigState], (state: Config.State): string => {
return state.environment.apis[key || 'default'].url;
});
return selector;
}
@ -104,18 +91,12 @@ export class ConfigState {
const selector = createSelector([ConfigState], (state: Config.State) => {
if (keyword) {
const keys = snq(
() =>
Object.keys(state.setting.values).filter(
key => key.indexOf(keyword) > -1,
),
() => Object.keys(state.setting.values).filter(key => key.indexOf(keyword) > -1),
[],
);
if (keys.length) {
return keys.reduce(
(acc, key) => ({ ...acc, [key]: state.setting.values[key] }),
{},
);
return keys.reduce((acc, key) => ({ ...acc, [key]: state.setting.values[key] }), {});
}
}
@ -125,32 +106,29 @@ export class ConfigState {
}
static getGrantedPolicy(key: string) {
const selector = createSelector(
[ConfigState],
(state: Config.State): boolean => {
if (!key) return true;
const getPolicy = k => snq(() => state.auth.grantedPolicies[k], false);
const selector = createSelector([ConfigState], (state: Config.State): boolean => {
if (!key) return true;
const getPolicy = k => snq(() => state.auth.grantedPolicies[k], false);
const orRegexp = /\|\|/g;
const andRegexp = /&&/g;
const orRegexp = /\|\|/g;
const andRegexp = /&&/g;
if (orRegexp.test(key)) {
const keys = key.split('||').filter(k => !!k);
if (orRegexp.test(key)) {
const keys = key.split('||').filter(k => !!k);
if (keys.length !== 2) return false;
if (keys.length !== 2) return false;
return getPolicy(keys[0].trim()) || getPolicy(keys[1].trim());
} else if (andRegexp.test(key)) {
const keys = key.split('&&').filter(k => !!k);
return getPolicy(keys[0].trim()) || getPolicy(keys[1].trim());
} else if (andRegexp.test(key)) {
const keys = key.split('&&').filter(k => !!k);
if (keys.length !== 2) return false;
if (keys.length !== 2) return false;
return getPolicy(keys[0].trim()) && getPolicy(keys[1].trim());
}
return getPolicy(keys[0].trim()) && getPolicy(keys[1].trim());
}
return getPolicy(key);
},
);
return getPolicy(key);
});
return selector;
}
@ -225,8 +203,7 @@ export class ConfigState {
}),
),
switchMap(configuration => {
let defaultLang: string =
configuration.setting.values['Abp.Localization.DefaultLanguage'];
let defaultLang: string = configuration.setting.values['Abp.Localization.DefaultLanguage'];
if (defaultLang.includes(';')) {
defaultLang = defaultLang.split(';')[0];
@ -246,12 +223,73 @@ export class ConfigState {
) {
let routes: ABP.FullRoute[] = getState().routes;
const index = routes.findIndex(route => route.name === name);
routes = patchRouteDeep(routes, name, newValue);
const flattedRoutes = getState().flattedRoutes;
const index = flattedRoutes.findIndex(route => route.name === name);
if (index > -1) {
flattedRoutes[index] = newValue as ABP.FullRoute;
}
return patchState({
routes,
flattedRoutes,
});
}
@Action(AddRoute)
addRoute({ patchState, getState }: StateContext<Config.State>, { payload }: AddRoute) {
let routes: ABP.FullRoute[] = getState().routes;
const flattedRoutes = getState().flattedRoutes;
const route: ABP.FullRoute = { ...payload };
if (route.parentName) {
const index = flattedRoutes.findIndex(r => r.name === route.parentName);
if (index < 0) return;
const parent = flattedRoutes[index];
if (parent.url.replace('/', '')) {
route.url = `${parent.url}/${route.path}`;
} else {
route.url = `/${route.path}`;
}
route.order = route.order || route.order === 0 ? route.order : parent.children.length;
parent.children = [...(parent.children || []), route].sort((a, b) => a.order - b.order);
flattedRoutes[index] = parent;
flattedRoutes.push(route);
let parentName = parent.name;
const parentNameArr = [parentName];
while (parentName) {
parentName = snq(() => flattedRoutes.find(r => r.name === parentName).parentName);
if (parentName) {
parentNameArr.unshift(parentName);
}
}
routes = updateRouteDeep(routes, parentNameArr, parent);
} else {
route.url = `/${route.path}`;
if (route.order || route.order === 0) {
routes = [...routes, route].sort((a, b) => a.order - b.order);
} else {
route.order = routes.length;
routes = [...routes, route];
}
flattedRoutes.push(route);
}
return patchState({
routes,
flattedRoutes,
});
}
}
@ -295,3 +333,25 @@ function patchRouteDeep(
return organizeRoutes(routes);
}
function updateRouteDeep(
routes: ABP.FullRoute[],
parentNameArr: string[],
newValue: ABP.FullRoute,
parentIndex = 0,
) {
const index = routes.findIndex(route => route.name === parentNameArr[parentIndex]);
if (parentIndex === parentNameArr.length - 1) {
routes[index] = newValue;
} else {
routes[index].children = updateRouteDeep(
routes[index].children,
parentNameArr,
newValue,
parentIndex + 1,
);
}
return routes;
}

13
npm/ng-packs/packages/core/src/lib/tests/config.plugin.spec.ts

@ -170,6 +170,7 @@ const expectedState = {
path: 'users',
name: 'AbpIdentity::Users',
order: 1,
parentName: 'AbpIdentity::Menu:IdentityManagement',
requiredPolicy: 'AbpIdentity.Users',
url: '/identity/users',
},
@ -177,6 +178,7 @@ const expectedState = {
path: 'roles',
name: 'AbpIdentity::Roles',
order: 2,
parentName: 'AbpIdentity::Menu:IdentityManagement',
requiredPolicy: 'AbpIdentity.Roles',
url: '/identity/roles',
},
@ -194,6 +196,7 @@ const expectedState = {
path: 'tenants',
name: 'AbpTenantManagement::Tenants',
order: 1,
parentName: 'AbpTenantManagement::Menu:TenantManagement',
requiredPolicy: 'AbpTenantManagement.Tenants',
url: '/tenant-management/tenants',
},
@ -215,6 +218,7 @@ const expectedState = {
path: 'users',
name: 'AbpIdentity::Users',
order: 1,
parentName: 'AbpIdentity::Menu:IdentityManagement',
requiredPolicy: 'AbpIdentity.Users',
url: '/identity/users',
},
@ -222,6 +226,7 @@ const expectedState = {
path: 'roles',
name: 'AbpIdentity::Roles',
order: 2,
parentName: 'AbpIdentity::Menu:IdentityManagement',
requiredPolicy: 'AbpIdentity.Roles',
url: '/identity/roles',
},
@ -232,6 +237,7 @@ const expectedState = {
path: 'users',
name: 'AbpIdentity::Users',
order: 1,
parentName: 'AbpIdentity::Menu:IdentityManagement',
requiredPolicy: 'AbpIdentity.Users',
url: '/identity/users',
},
@ -239,6 +245,7 @@ const expectedState = {
path: 'roles',
name: 'AbpIdentity::Roles',
order: 2,
parentName: 'AbpIdentity::Menu:IdentityManagement',
requiredPolicy: 'AbpIdentity.Roles',
url: '/identity/roles',
},
@ -253,6 +260,7 @@ const expectedState = {
path: 'tenants',
name: 'AbpTenantManagement::Tenants',
order: 1,
parentName: 'AbpTenantManagement::Menu:TenantManagement',
requiredPolicy: 'AbpTenantManagement.Tenants',
url: '/tenant-management/tenants',
},
@ -264,6 +272,7 @@ const expectedState = {
path: 'tenants',
name: 'AbpTenantManagement::Tenants',
order: 1,
parentName: 'AbpTenantManagement::Menu:TenantManagement',
requiredPolicy: 'AbpTenantManagement.Tenants',
url: '/tenant-management/tenants',
},
@ -277,12 +286,14 @@ const expectedState = {
path: 'login',
name: 'AbpAccount::Login',
order: 1,
parentName: 'AbpAccount::Menu:Account',
url: '/account/login',
},
{
path: 'register',
name: 'AbpAccount::Register',
order: 2,
parentName: 'AbpAccount::Menu:Account',
url: '/account/register',
},
],
@ -293,12 +304,14 @@ const expectedState = {
path: 'login',
name: 'AbpAccount::Login',
order: 1,
parentName: 'AbpAccount::Menu:Account',
url: '/account/login',
},
{
path: 'register',
name: 'AbpAccount::Register',
order: 2,
parentName: 'AbpAccount::Menu:Account',
url: '/account/register',
},
],

Loading…
Cancel
Save