-
Notifications
You must be signed in to change notification settings - Fork 3.3k
/
config.plugin.ts
115 lines (95 loc) · 3.53 KB
/
config.plugin.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import { Inject, Injectable, InjectionToken } from '@angular/core';
import { Router, Routes } from '@angular/router';
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';
import clone from 'just-clone';
export const NGXS_CONFIG_PLUGIN_OPTIONS = new InjectionToken('NGXS_CONFIG_PLUGIN_OPTIONS');
@Injectable()
export class ConfigPlugin implements NgxsPlugin {
private initialized = false;
constructor(@Inject(NGXS_CONFIG_PLUGIN_OPTIONS) private options: ABP.Root, private router: Router) {}
handle(state: any, event: any, next: NgxsNextPluginFn) {
const matches = actionMatcher(event);
const isInitAction = matches(InitState) || matches(UpdateState);
if (isInitAction && !this.initialized) {
const transformedRoutes = transformRoutes(this.router.config);
let { routes } = transformedRoutes;
const { wrappers } = transformedRoutes;
routes = organizeRoutes(routes, wrappers);
const flattedRoutes = flatRoutes(clone(routes));
state = setValue(state, 'ConfigState', {
...(state.ConfigState && { ...state.ConfigState }),
...this.options,
routes,
flattedRoutes,
});
this.initialized = true;
}
return next(state, event);
}
}
function transformRoutes(routes: Routes = [], wrappers: ABP.FullRoute[] = []): any {
// TODO: remove in v1
const oldAbpRoutes: ABP.FullRoute[] = routes
.filter(route => {
return snq(() => route.data.routes.routes.find(r => r.path === route.path), false);
})
.reduce((acc, val) => [...acc, ...val.data.routes.routes], []);
// tslint:disable-next-line: deprecation
const abpRoutes = [...getAbpRoutes(), ...oldAbpRoutes];
wrappers = abpRoutes.filter(ar => ar.wrapper);
const transformed = [] as ABP.FullRoute[];
routes
.filter(route => route.component || route.loadChildren)
.forEach(route => {
const abpPackage = abpRoutes.find(abp => abp.path.toLowerCase() === route.path.toLowerCase() && !abp.wrapper);
const { length } = transformed;
if (abpPackage) {
transformed.push(abpPackage);
}
if (transformed.length === length && (route.data || {}).routes) {
transformed.push({
...route.data.routes,
path: route.path,
name: snq(() => route.data.routes.name, route.path),
children: route.data.routes.children || [],
} as ABP.FullRoute);
}
});
return { routes: setUrls(transformed), wrappers };
}
function setUrls(routes: ABP.FullRoute[], parentUrl?: string): ABP.FullRoute[] {
if (parentUrl) {
// this if block using for only recursive call
return routes.map(route => ({
...route,
url: `${parentUrl}/${route.path}`,
...(route.children &&
route.children.length && {
children: setUrls(route.children, `${parentUrl}/${route.path}`),
}),
}));
}
return routes.map(route => ({
...route,
url: `/${route.path}`,
...(route.children &&
route.children.length && {
children: setUrls(route.children, `/${route.path}`),
}),
}));
}
function flatRoutes(routes: ABP.FullRoute[]): ABP.FullRoute[] {
const flat = (r: ABP.FullRoute[]) => {
return r.reduce((acc, val) => {
let value: ABP.FullRoute[] = [val];
if (val.children) {
value = [val, ...flat(val.children)];
}
return [...acc, ...value];
}, []);
};
return flat(routes);
}