@ngrdt/router 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -0
- package/esm2022/index.mjs +9 -0
- package/esm2022/lib/directives/rdt-router-link.directive.mjs +69 -0
- package/esm2022/lib/rdt-route/constants.mjs +5 -0
- package/esm2022/lib/rdt-route/rdt-angular-route.mjs +173 -0
- package/esm2022/lib/rdt-route/rdt-route-builder.mjs +70 -0
- package/esm2022/lib/rdt-route/rdt-route.mjs +208 -0
- package/esm2022/lib/rdt-route/utils.mjs +2 -0
- package/esm2022/lib/services/rdt-confirm-data-loss.service.mjs +11 -0
- package/esm2022/lib/services/rdt-router.service.mjs +128 -0
- package/esm2022/lib/services/rdt-routes.token.mjs +3 -0
- package/esm2022/ngrdt-router.mjs +5 -0
- package/fesm2022/ngrdt-router.mjs +660 -0
- package/fesm2022/ngrdt-router.mjs.map +1 -0
- package/index.d.ts +8 -0
- package/lib/directives/rdt-router-link.directive.d.ts +23 -0
- package/lib/rdt-route/constants.d.ts +3 -0
- package/lib/rdt-route/rdt-angular-route.d.ts +28 -0
- package/lib/rdt-route/rdt-route-builder.d.ts +12 -0
- package/lib/rdt-route/rdt-route.d.ts +48 -0
- package/lib/rdt-route/utils.d.ts +10 -0
- package/lib/services/rdt-confirm-data-loss.service.d.ts +9 -0
- package/lib/services/rdt-router.service.d.ts +41 -0
- package/lib/services/rdt-routes.token.d.ts +3 -0
- package/package.json +25 -0
|
@@ -0,0 +1,660 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { InjectionToken, inject, Injectable, EnvironmentInjector, runInInjectionContext, booleanAttribute, Directive, Input } from '@angular/core';
|
|
3
|
+
import { defer, of, filter, take } from 'rxjs';
|
|
4
|
+
import { Location, PlatformLocation } from '@angular/common';
|
|
5
|
+
import * as i1 from '@angular/router';
|
|
6
|
+
import { Router, NavigationEnd, RouterLink } from '@angular/router';
|
|
7
|
+
import { RdtStringUtils } from '@ngrdt/utils';
|
|
8
|
+
|
|
9
|
+
const RDT_CONFIRM_DATA_LOSS_SERVICE = new InjectionToken('RDT_CONFIRM_DATA_LOSS_SERVICE', { factory: () => new RdtConfirmDataLossServiceAlert() });
|
|
10
|
+
class RdtConfirmDataLossService {
|
|
11
|
+
}
|
|
12
|
+
class RdtConfirmDataLossServiceAlert extends RdtConfirmDataLossService {
|
|
13
|
+
confirmDataLoss() {
|
|
14
|
+
return defer(() => of(confirm('Are you sure you want to leave this page?')));
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const RDT_ROUTES_TOKEN = new InjectionToken('RDT_ROUTES_TOKEN');
|
|
19
|
+
|
|
20
|
+
class RdtRouterService {
|
|
21
|
+
allRoutes = inject(RDT_ROUTES_TOKEN, { optional: true });
|
|
22
|
+
location = inject(Location);
|
|
23
|
+
router = inject(Router);
|
|
24
|
+
baseHref = inject(PlatformLocation).getBaseHrefFromDOM();
|
|
25
|
+
_previousUrl = null;
|
|
26
|
+
_currentUrl = null;
|
|
27
|
+
get previousUrl() {
|
|
28
|
+
return this._previousUrl;
|
|
29
|
+
}
|
|
30
|
+
get currentUrl() {
|
|
31
|
+
return this._currentUrl;
|
|
32
|
+
}
|
|
33
|
+
parsePreviousUrl() {
|
|
34
|
+
return this._previousUrl ? this.parseAbsoluteUrl(this._previousUrl) : null;
|
|
35
|
+
}
|
|
36
|
+
parseCurrentUrl() {
|
|
37
|
+
return this._currentUrl ? this.parseAbsoluteUrl(this._currentUrl) : null;
|
|
38
|
+
}
|
|
39
|
+
navigationEnd$ = this.router.events.pipe(filter((e) => e instanceof NavigationEnd));
|
|
40
|
+
nextNavigationEnd$ = this.navigationEnd$.pipe(take(1));
|
|
41
|
+
constructor() {
|
|
42
|
+
if (this.allRoutes === null) {
|
|
43
|
+
console.warn('All routes not provided. Make sure to provide RDT_ROUTES_TOKEN with RdtRoute[].');
|
|
44
|
+
this.allRoutes = [];
|
|
45
|
+
}
|
|
46
|
+
this.navigationEnd$.subscribe((e) => {
|
|
47
|
+
this._previousUrl = this._currentUrl;
|
|
48
|
+
this._currentUrl = e.url;
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
navigate(link, params, target = '_self') {
|
|
52
|
+
const url = params
|
|
53
|
+
? link.createAbsoluteUrl(params)
|
|
54
|
+
: link.createAbsoluteUrl();
|
|
55
|
+
if (target === '_self') {
|
|
56
|
+
return this.router.navigate([url], {
|
|
57
|
+
queryParams: link.queryParams,
|
|
58
|
+
state: link.stateParams,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
const absolutePath = RdtStringUtils.createAbsoluteUrl(url, this.baseHref);
|
|
62
|
+
const pathWithParams = RdtStringUtils.appendQueryParams(absolutePath, link.queryParams);
|
|
63
|
+
const win = window.open(pathWithParams, target);
|
|
64
|
+
if (win) {
|
|
65
|
+
win.RdtStateParams = link.stateParams;
|
|
66
|
+
}
|
|
67
|
+
return Promise.resolve(true);
|
|
68
|
+
}
|
|
69
|
+
navigateHome(params) {
|
|
70
|
+
return this.router.navigateByUrl(RdtStringUtils.appendQueryParams('/', params?.query ?? {}), {
|
|
71
|
+
state: params?.state,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
parseAbsoluteUrl(url = this.location.path()) {
|
|
75
|
+
if (this.allRoutes) {
|
|
76
|
+
for (const route of this.allRoutes) {
|
|
77
|
+
const params = route.parseAbsoluteUrl(url);
|
|
78
|
+
if (params) {
|
|
79
|
+
return { route, params };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
navigateBack(params) {
|
|
86
|
+
const parsed = this.parseAbsoluteUrl();
|
|
87
|
+
if (parsed) {
|
|
88
|
+
let route = parsed.route.withStaticParams(parsed.params);
|
|
89
|
+
do {
|
|
90
|
+
route = route.parent;
|
|
91
|
+
} while (route && route.entryDisabled);
|
|
92
|
+
// In case route has no ancestor with allowed entry,
|
|
93
|
+
if (!route) {
|
|
94
|
+
return this.navigateHome(params);
|
|
95
|
+
}
|
|
96
|
+
if (params) {
|
|
97
|
+
if (params.query) {
|
|
98
|
+
route = route.withQueryParams(params.query);
|
|
99
|
+
}
|
|
100
|
+
if (params.state) {
|
|
101
|
+
route = route.withStateParams(params.state);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return this.navigate(route);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
console.warn(`Cannot go back from ${this.location.path()} because no route matches current url`);
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
extractAllParams(currentRoute) {
|
|
112
|
+
if (!currentRoute) {
|
|
113
|
+
const parsed = this.parseAbsoluteUrl();
|
|
114
|
+
if (!parsed) {
|
|
115
|
+
console.warn('No route matches current url.');
|
|
116
|
+
return {};
|
|
117
|
+
}
|
|
118
|
+
currentRoute = parsed.route;
|
|
119
|
+
}
|
|
120
|
+
const url = this.location.path();
|
|
121
|
+
return currentRoute.parseAbsoluteUrl(url);
|
|
122
|
+
}
|
|
123
|
+
isParentOfCurrentLocation(route) {
|
|
124
|
+
console.log(this.parseAbsoluteUrl());
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
removeQueryParams(...paramNames) {
|
|
128
|
+
const regex = new RegExp(`[?&](${paramNames.join('|')})=[^&]*`, 'g');
|
|
129
|
+
return history.replaceState(null, '', location.pathname + location.search.replace(regex, '').replace(/^&/, '?'));
|
|
130
|
+
}
|
|
131
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: RdtRouterService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
132
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: RdtRouterService, providedIn: 'root' });
|
|
133
|
+
}
|
|
134
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: RdtRouterService, decorators: [{
|
|
135
|
+
type: Injectable,
|
|
136
|
+
args: [{
|
|
137
|
+
providedIn: 'root',
|
|
138
|
+
}]
|
|
139
|
+
}], ctorParameters: () => [] });
|
|
140
|
+
|
|
141
|
+
var RdtNavigationSource;
|
|
142
|
+
(function (RdtNavigationSource) {
|
|
143
|
+
RdtNavigationSource["BREADCRUMB"] = "breadcrumb";
|
|
144
|
+
})(RdtNavigationSource || (RdtNavigationSource = {}));
|
|
145
|
+
|
|
146
|
+
class RdtAngularRoute {
|
|
147
|
+
route;
|
|
148
|
+
children = [];
|
|
149
|
+
// Must be set from component declaration files
|
|
150
|
+
loadChildren;
|
|
151
|
+
component;
|
|
152
|
+
providers = [];
|
|
153
|
+
resolvers = {};
|
|
154
|
+
canActivate = [];
|
|
155
|
+
canActivateChild = [];
|
|
156
|
+
canDeactivate = [];
|
|
157
|
+
runGuardsAndResolvers;
|
|
158
|
+
constructor(route) {
|
|
159
|
+
this.route = route;
|
|
160
|
+
}
|
|
161
|
+
provide(...providers) {
|
|
162
|
+
this.providers.push(...providers);
|
|
163
|
+
return this;
|
|
164
|
+
}
|
|
165
|
+
setModule(callback) {
|
|
166
|
+
this.loadChildren = callback;
|
|
167
|
+
return this;
|
|
168
|
+
}
|
|
169
|
+
setComponent(comp) {
|
|
170
|
+
this.component = comp;
|
|
171
|
+
return this;
|
|
172
|
+
}
|
|
173
|
+
setChildren(...routes) {
|
|
174
|
+
this.children = routes;
|
|
175
|
+
return this;
|
|
176
|
+
}
|
|
177
|
+
addResolve(paramName, resolver) {
|
|
178
|
+
this.resolvers[paramName] = resolver;
|
|
179
|
+
return this;
|
|
180
|
+
}
|
|
181
|
+
addCanActivate(...fns) {
|
|
182
|
+
this.canActivate.push(...fns);
|
|
183
|
+
return this;
|
|
184
|
+
}
|
|
185
|
+
addCanDeactivate(...fns) {
|
|
186
|
+
this.canDeactivate.push(...fns);
|
|
187
|
+
return this;
|
|
188
|
+
}
|
|
189
|
+
addCanActivateChild(...fns) {
|
|
190
|
+
this.canActivateChild.push(...fns);
|
|
191
|
+
return this;
|
|
192
|
+
}
|
|
193
|
+
setRunGuardsAndResolvers(value) {
|
|
194
|
+
this.runGuardsAndResolvers = value;
|
|
195
|
+
return this;
|
|
196
|
+
}
|
|
197
|
+
build() {
|
|
198
|
+
this.checkChildrenMatch();
|
|
199
|
+
let res = {
|
|
200
|
+
path: this.route.path,
|
|
201
|
+
providers: this.providers,
|
|
202
|
+
title: this.route.name,
|
|
203
|
+
canMatch: this.getCanMatch(),
|
|
204
|
+
};
|
|
205
|
+
if (this.component) {
|
|
206
|
+
res.component = this.component;
|
|
207
|
+
}
|
|
208
|
+
else if (this.loadChildren) {
|
|
209
|
+
res.loadChildren = this.loadChildren;
|
|
210
|
+
}
|
|
211
|
+
res.data = {
|
|
212
|
+
breadcrumb: {
|
|
213
|
+
label: this.route.name,
|
|
214
|
+
disable: this.route.entryDisabled,
|
|
215
|
+
staticStateParams: {
|
|
216
|
+
src: RdtNavigationSource.BREADCRUMB,
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
};
|
|
220
|
+
const guard = () => {
|
|
221
|
+
const injector = inject(EnvironmentInjector);
|
|
222
|
+
return runInInjectionContext(injector, this.route.canBeEntered.bind(this.route));
|
|
223
|
+
};
|
|
224
|
+
this.canActivate.push(guard);
|
|
225
|
+
this.canActivateChild.push(guard);
|
|
226
|
+
res.canActivate = this.canActivate;
|
|
227
|
+
res.canDeactivate = this.canDeactivate;
|
|
228
|
+
// If children exist, change
|
|
229
|
+
// {
|
|
230
|
+
// path: '/path',
|
|
231
|
+
// component: FeatureComponent,
|
|
232
|
+
// children: [...]
|
|
233
|
+
// }
|
|
234
|
+
// into
|
|
235
|
+
// {
|
|
236
|
+
// path: '/path',
|
|
237
|
+
// children: [
|
|
238
|
+
// {
|
|
239
|
+
// path: '',
|
|
240
|
+
// component: FeatureComponent
|
|
241
|
+
// },
|
|
242
|
+
// ...
|
|
243
|
+
// ]
|
|
244
|
+
// }
|
|
245
|
+
if (this.children.length > 0) {
|
|
246
|
+
if (this.loadChildren || this.component) {
|
|
247
|
+
const path = res.path;
|
|
248
|
+
res.path = '';
|
|
249
|
+
res.pathMatch = 'full';
|
|
250
|
+
res.canMatch = undefined;
|
|
251
|
+
res = {
|
|
252
|
+
path: path,
|
|
253
|
+
children: [res, ...this.children],
|
|
254
|
+
canActivateChild: this.canActivateChild,
|
|
255
|
+
canMatch: this.getCanMatch(),
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
res.children = this.children;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
if (Object.keys(this.resolvers).length > 0) {
|
|
263
|
+
res.resolve = this.resolvers;
|
|
264
|
+
}
|
|
265
|
+
if (this.runGuardsAndResolvers) {
|
|
266
|
+
res.runGuardsAndResolvers = this.runGuardsAndResolvers;
|
|
267
|
+
}
|
|
268
|
+
return res;
|
|
269
|
+
}
|
|
270
|
+
getCanMatch() {
|
|
271
|
+
const paramMap = this.route.paramMap;
|
|
272
|
+
const hasNumberParams = Object.keys(paramMap).some((p) => paramMap[p] === 'number');
|
|
273
|
+
if (!hasNumberParams) {
|
|
274
|
+
return undefined;
|
|
275
|
+
}
|
|
276
|
+
const routeSegmentLength = this.route.path.split('/').length;
|
|
277
|
+
const regex = new RegExp(`^${this.route.regex.source}$`);
|
|
278
|
+
return [
|
|
279
|
+
(route, segments) => {
|
|
280
|
+
const path = segments
|
|
281
|
+
.slice(0, routeSegmentLength)
|
|
282
|
+
.map((s) => s.path)
|
|
283
|
+
.join('/');
|
|
284
|
+
return regex.test(path);
|
|
285
|
+
},
|
|
286
|
+
];
|
|
287
|
+
}
|
|
288
|
+
checkChildrenMatch() {
|
|
289
|
+
// Check that all routes are present if route is not
|
|
290
|
+
// lazy loaded module.
|
|
291
|
+
if (!this.loadChildren &&
|
|
292
|
+
(this.route.children.length > 0 || this.children.length > 0)) {
|
|
293
|
+
if (this.children.length < this.route.children.length) {
|
|
294
|
+
throw new Error(`RdtRoute ${this.route.name} has ${this.route.children.length} children, but RdtAngularRoute has ${this.children.length}. These numbers must match. Did you forget to call .setChildren() method in global routes definition? Routes with following names should be present: ${this.route.children
|
|
295
|
+
.map((ch) => ch.name)
|
|
296
|
+
.join(', ')}`);
|
|
297
|
+
}
|
|
298
|
+
else if (this.children.length > this.route.children.length) {
|
|
299
|
+
throw new Error(`RdtRoute ${this.route.name} has ${this.route.children.length} children, but RdtAngularRoute has ${this.children.length}. These numbers must match. Did you forget to call .setChildren() method in feature shell routes definition? Routes with following paths should be present: ${this.children
|
|
300
|
+
.map((ch) => ch.path)
|
|
301
|
+
.join(', ')}`);
|
|
302
|
+
}
|
|
303
|
+
const n1 = this.children.map((ch) => ch.path);
|
|
304
|
+
const n2 = this.route.children.map((ch) => ch.path);
|
|
305
|
+
n1.sort();
|
|
306
|
+
n2.sort();
|
|
307
|
+
for (let i = 0; i < n1.length; i++) {
|
|
308
|
+
if (n1[i] !== n2[i]) {
|
|
309
|
+
throw new Error(`Paths of children provided in RdtRoute and
|
|
310
|
+
RdtAngularRoute do not match. ${n1[i]} != ${n2[i]}`);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
class RdtRoute {
|
|
318
|
+
orderedParams = [];
|
|
319
|
+
_paramMap = {};
|
|
320
|
+
_regex;
|
|
321
|
+
paramMappings = [];
|
|
322
|
+
_staticParams = {};
|
|
323
|
+
_queryParams = {};
|
|
324
|
+
_stateParams = {};
|
|
325
|
+
_name;
|
|
326
|
+
_path;
|
|
327
|
+
_parent = null;
|
|
328
|
+
_children = [];
|
|
329
|
+
_entryDisabled = false;
|
|
330
|
+
_canBeEntered = () => true;
|
|
331
|
+
_absoluteRegex;
|
|
332
|
+
get paramMap() {
|
|
333
|
+
return this._paramMap;
|
|
334
|
+
}
|
|
335
|
+
get name() {
|
|
336
|
+
return this._name;
|
|
337
|
+
}
|
|
338
|
+
get path() {
|
|
339
|
+
return this._path;
|
|
340
|
+
}
|
|
341
|
+
get parent() {
|
|
342
|
+
return this._parent;
|
|
343
|
+
}
|
|
344
|
+
get children() {
|
|
345
|
+
return this._children;
|
|
346
|
+
}
|
|
347
|
+
get basePath() {
|
|
348
|
+
return this._parent ? this._parent.absolutePath : '/';
|
|
349
|
+
}
|
|
350
|
+
get absolutePath() {
|
|
351
|
+
return RdtStringUtils.joinPaths(this.basePath, this._path);
|
|
352
|
+
}
|
|
353
|
+
get regex() {
|
|
354
|
+
return this._regex;
|
|
355
|
+
}
|
|
356
|
+
get absoluteRegex() {
|
|
357
|
+
if (this._absoluteRegex) {
|
|
358
|
+
return this._absoluteRegex;
|
|
359
|
+
}
|
|
360
|
+
if (this._parent) {
|
|
361
|
+
// Remove initial ^ and ending $
|
|
362
|
+
const parent = this._parent.absoluteRegex.source.slice(1, -1);
|
|
363
|
+
this._absoluteRegex = new RegExp('^' + RdtStringUtils.joinPaths(parent, this._regex.source) + '$');
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
this._absoluteRegex = new RegExp('^' + RdtStringUtils.joinPaths('/', this._regex.source) + '$');
|
|
367
|
+
}
|
|
368
|
+
return this._absoluteRegex;
|
|
369
|
+
}
|
|
370
|
+
get entryDisabled() {
|
|
371
|
+
return this._entryDisabled;
|
|
372
|
+
}
|
|
373
|
+
get stateParams() {
|
|
374
|
+
return this._stateParams;
|
|
375
|
+
}
|
|
376
|
+
get queryParams() {
|
|
377
|
+
return this._queryParams;
|
|
378
|
+
}
|
|
379
|
+
testUrl(url) {
|
|
380
|
+
return this.absoluteRegex.test(url);
|
|
381
|
+
}
|
|
382
|
+
get staticParams() {
|
|
383
|
+
return { ...this._staticParams };
|
|
384
|
+
}
|
|
385
|
+
canBeEntered(injector) {
|
|
386
|
+
return injector
|
|
387
|
+
? runInInjectionContext(injector, this._canBeEntered)
|
|
388
|
+
: this._canBeEntered();
|
|
389
|
+
}
|
|
390
|
+
// Extracts url parameters from absolute url.
|
|
391
|
+
parseAbsoluteUrl(url) {
|
|
392
|
+
const reg = this.absoluteRegex;
|
|
393
|
+
if (!reg.test(url)) {
|
|
394
|
+
return null;
|
|
395
|
+
}
|
|
396
|
+
const matches = reg.exec(url);
|
|
397
|
+
if (matches) {
|
|
398
|
+
const values = matches.slice(1).reverse();
|
|
399
|
+
return this.fill(values);
|
|
400
|
+
}
|
|
401
|
+
else {
|
|
402
|
+
return null;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
fill(values, res = {}) {
|
|
406
|
+
const params = {};
|
|
407
|
+
const reversedParams = this.orderedParams.slice().reverse();
|
|
408
|
+
for (let i = 0; i < reversedParams.length && i < values.length; i++) {
|
|
409
|
+
const key = reversedParams[i];
|
|
410
|
+
const mappedKey = this.paramMappings.find((m) => m.urlName === key)?.tableName ?? key;
|
|
411
|
+
let val = values[i];
|
|
412
|
+
if (this._paramMap[key] === 'number') {
|
|
413
|
+
val = parseInt(val);
|
|
414
|
+
}
|
|
415
|
+
params[mappedKey] = val;
|
|
416
|
+
}
|
|
417
|
+
res[this.absolutePath] = params;
|
|
418
|
+
if (values.length > reversedParams.length && this._parent) {
|
|
419
|
+
this._parent.fill(values.slice(reversedParams.length), res);
|
|
420
|
+
}
|
|
421
|
+
return res;
|
|
422
|
+
}
|
|
423
|
+
createAbsoluteUrl(paramMap = this._staticParams) {
|
|
424
|
+
if (!this._parent) {
|
|
425
|
+
return this.createUrl(this.absolutePath, paramMap);
|
|
426
|
+
}
|
|
427
|
+
else {
|
|
428
|
+
return RdtStringUtils.joinPaths(this._parent.createAbsoluteUrl(), this.createRelativeUrl(paramMap));
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
createRelativeUrl(paramMap = this._staticParams) {
|
|
432
|
+
return this.createUrl(this.path, paramMap);
|
|
433
|
+
}
|
|
434
|
+
createUrl(path, paramMap) {
|
|
435
|
+
const paramNames = Object.keys(this._paramMap);
|
|
436
|
+
paramNames.sort((a, b) => b.length - a.length);
|
|
437
|
+
const extendedParamMap = { ...paramMap };
|
|
438
|
+
this.paramMappings.forEach((mapping) => {
|
|
439
|
+
if (mapping.tableName in paramMap) {
|
|
440
|
+
extendedParamMap[mapping.urlName] = paramMap[mapping.tableName];
|
|
441
|
+
}
|
|
442
|
+
});
|
|
443
|
+
paramNames.forEach((param) => {
|
|
444
|
+
path = path.replace(`:${param}`, `${extendedParamMap[param]}`);
|
|
445
|
+
});
|
|
446
|
+
return path;
|
|
447
|
+
}
|
|
448
|
+
toAngularRoute() {
|
|
449
|
+
if (!this._regex) {
|
|
450
|
+
throw new Error('You have to first call .build() on route!');
|
|
451
|
+
}
|
|
452
|
+
return new RdtAngularRoute(this);
|
|
453
|
+
}
|
|
454
|
+
// Provides static mapping for parameter names tableName -> urlName.
|
|
455
|
+
// Returns new instance of Dp3Route<T> that is clone of
|
|
456
|
+
// this route and its parents (NOT children).
|
|
457
|
+
withParamMappings(mappings) {
|
|
458
|
+
const clone = this.clone();
|
|
459
|
+
clone.paramMappings = mappings;
|
|
460
|
+
return clone;
|
|
461
|
+
}
|
|
462
|
+
// Sets selected parameters for itself and parents.
|
|
463
|
+
// Returns new instance of Dp3Route<T> that is clone of
|
|
464
|
+
// this route and its parents (NOT children).
|
|
465
|
+
withStaticParams(param1, param2) {
|
|
466
|
+
const clone = this.clone();
|
|
467
|
+
if (param2) {
|
|
468
|
+
const routeAbsPath = param1.absolutePath;
|
|
469
|
+
let current = clone;
|
|
470
|
+
while (current) {
|
|
471
|
+
if (current.absolutePath === routeAbsPath) {
|
|
472
|
+
current._staticParams = param2;
|
|
473
|
+
}
|
|
474
|
+
current = current._parent;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
else {
|
|
478
|
+
clone._staticParams = param1;
|
|
479
|
+
}
|
|
480
|
+
return clone;
|
|
481
|
+
}
|
|
482
|
+
withQueryParams(queryParams) {
|
|
483
|
+
const clone = this.clone();
|
|
484
|
+
clone._queryParams = { ...queryParams };
|
|
485
|
+
return clone;
|
|
486
|
+
}
|
|
487
|
+
withStateParams(stateParams) {
|
|
488
|
+
const clone = this.clone();
|
|
489
|
+
clone._stateParams = { ...stateParams };
|
|
490
|
+
return clone;
|
|
491
|
+
}
|
|
492
|
+
// Returns Partial of object that only contains properties
|
|
493
|
+
// necessary to create this route.
|
|
494
|
+
extractRouteParams(row) {
|
|
495
|
+
const res = {};
|
|
496
|
+
this.orderedParams.forEach((param) => {
|
|
497
|
+
const mapping = this.paramMappings.find((m) => m.urlName === param);
|
|
498
|
+
const mappedParam = (mapping?.tableName ?? param);
|
|
499
|
+
if (mappedParam in row) {
|
|
500
|
+
res[mappedParam] = row[mappedParam];
|
|
501
|
+
}
|
|
502
|
+
});
|
|
503
|
+
return res;
|
|
504
|
+
}
|
|
505
|
+
// Returns new instance of Dp3Route<T> that is clone of
|
|
506
|
+
// this route and its parents (NOT children).
|
|
507
|
+
clone() {
|
|
508
|
+
const clone = new RdtRoute();
|
|
509
|
+
clone._name = this._name;
|
|
510
|
+
clone._parent = this._parent?.clone() ?? null;
|
|
511
|
+
clone._path = this.path;
|
|
512
|
+
clone._entryDisabled = this._entryDisabled;
|
|
513
|
+
clone.orderedParams = [...this.orderedParams];
|
|
514
|
+
clone._paramMap = { ...this._paramMap };
|
|
515
|
+
clone._regex = new RegExp(this._regex);
|
|
516
|
+
clone.paramMappings = this.paramMappings;
|
|
517
|
+
clone._staticParams = this._staticParams;
|
|
518
|
+
return clone;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
const DEFAULT_PARAM_TYPE = 'number';
|
|
523
|
+
class RdtRouteBuilder extends RdtRoute {
|
|
524
|
+
setCanBeEntered(fn) {
|
|
525
|
+
this._canBeEntered = fn;
|
|
526
|
+
return this;
|
|
527
|
+
}
|
|
528
|
+
setEntryDisabled(value = true) {
|
|
529
|
+
this._entryDisabled = value;
|
|
530
|
+
return this;
|
|
531
|
+
}
|
|
532
|
+
setPath(path) {
|
|
533
|
+
this._path = path;
|
|
534
|
+
const s = path.split('/');
|
|
535
|
+
const params = [];
|
|
536
|
+
s.forEach((part) => {
|
|
537
|
+
if (part.includes(':')) {
|
|
538
|
+
const param = part.split(':')[1];
|
|
539
|
+
if (param) {
|
|
540
|
+
params.push(param);
|
|
541
|
+
if (!this._paramMap[param]) {
|
|
542
|
+
this._paramMap[param] = DEFAULT_PARAM_TYPE;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
});
|
|
547
|
+
this.orderedParams = params;
|
|
548
|
+
return this;
|
|
549
|
+
}
|
|
550
|
+
setParam(paramName, type) {
|
|
551
|
+
this._paramMap[paramName] = type;
|
|
552
|
+
return this;
|
|
553
|
+
}
|
|
554
|
+
setName(name) {
|
|
555
|
+
this._name = name;
|
|
556
|
+
return this;
|
|
557
|
+
}
|
|
558
|
+
setChildren(...children) {
|
|
559
|
+
this._children = children;
|
|
560
|
+
for (const child of children) {
|
|
561
|
+
child._parent = this;
|
|
562
|
+
}
|
|
563
|
+
return this;
|
|
564
|
+
}
|
|
565
|
+
build() {
|
|
566
|
+
if (typeof this._path !== 'string') {
|
|
567
|
+
throw new Error('Please provide path for route. Empty string is acceptable.');
|
|
568
|
+
}
|
|
569
|
+
this.setRegex();
|
|
570
|
+
return this;
|
|
571
|
+
}
|
|
572
|
+
setRegex() {
|
|
573
|
+
const params = Object.keys(this._paramMap);
|
|
574
|
+
params.sort((a, b) => b.length - a.length);
|
|
575
|
+
let substituted = this.path;
|
|
576
|
+
params.forEach((p) => {
|
|
577
|
+
const type = this._paramMap[p];
|
|
578
|
+
if (!type) {
|
|
579
|
+
throw new Error('Params is not set i');
|
|
580
|
+
}
|
|
581
|
+
substituted = substituted.replace(`:${p}`, RdtRouteBuilder.groups[type]);
|
|
582
|
+
});
|
|
583
|
+
this._regex = new RegExp(substituted);
|
|
584
|
+
}
|
|
585
|
+
static groups = {
|
|
586
|
+
string: '(.+)',
|
|
587
|
+
number: '(\\d+)',
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
class RdtRouterLinkDirective {
|
|
592
|
+
routerLinkRef = inject(RouterLink, { self: true });
|
|
593
|
+
envInjector = inject(EnvironmentInjector);
|
|
594
|
+
route;
|
|
595
|
+
target = '_self';
|
|
596
|
+
params;
|
|
597
|
+
queryParams;
|
|
598
|
+
stateParams;
|
|
599
|
+
disabled = false;
|
|
600
|
+
ngOnInit() {
|
|
601
|
+
this.update();
|
|
602
|
+
}
|
|
603
|
+
ngOnChanges() {
|
|
604
|
+
this.update();
|
|
605
|
+
}
|
|
606
|
+
update() {
|
|
607
|
+
if (this.route.canBeEntered(this.envInjector) && !this.disabled) {
|
|
608
|
+
this.setLink();
|
|
609
|
+
}
|
|
610
|
+
else {
|
|
611
|
+
this.disableLink();
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
setLink() {
|
|
615
|
+
this.routerLinkRef.routerLink = this.route.createAbsoluteUrl(this.params);
|
|
616
|
+
this.routerLinkRef.state = this.stateParams ?? this.route.stateParams;
|
|
617
|
+
this.routerLinkRef.queryParams = this.queryParams ?? this.route.queryParams;
|
|
618
|
+
this.routerLinkRef.ngOnChanges({});
|
|
619
|
+
}
|
|
620
|
+
disableLink() {
|
|
621
|
+
this.routerLinkRef.routerLink = null;
|
|
622
|
+
this.routerLinkRef.ngOnChanges({});
|
|
623
|
+
}
|
|
624
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: RdtRouterLinkDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
625
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "18.2.7", type: RdtRouterLinkDirective, isStandalone: true, selector: "[rdtRouterLink]", inputs: { route: ["rdtRouterLink", "route"], target: "target", params: "params", queryParams: "queryParams", stateParams: "stateParams", disabled: ["disabled", "disabled", booleanAttribute] }, usesOnChanges: true, hostDirectives: [{ directive: i1.RouterLink, inputs: ["target", "target"] }], ngImport: i0 });
|
|
626
|
+
}
|
|
627
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: RdtRouterLinkDirective, decorators: [{
|
|
628
|
+
type: Directive,
|
|
629
|
+
args: [{
|
|
630
|
+
selector: '[rdtRouterLink]',
|
|
631
|
+
standalone: true,
|
|
632
|
+
hostDirectives: [
|
|
633
|
+
{
|
|
634
|
+
directive: RouterLink,
|
|
635
|
+
inputs: ['target'],
|
|
636
|
+
},
|
|
637
|
+
],
|
|
638
|
+
}]
|
|
639
|
+
}], propDecorators: { route: [{
|
|
640
|
+
type: Input,
|
|
641
|
+
args: [{ alias: 'rdtRouterLink', required: true }]
|
|
642
|
+
}], target: [{
|
|
643
|
+
type: Input
|
|
644
|
+
}], params: [{
|
|
645
|
+
type: Input
|
|
646
|
+
}], queryParams: [{
|
|
647
|
+
type: Input
|
|
648
|
+
}], stateParams: [{
|
|
649
|
+
type: Input
|
|
650
|
+
}], disabled: [{
|
|
651
|
+
type: Input,
|
|
652
|
+
args: [{ transform: booleanAttribute }]
|
|
653
|
+
}] } });
|
|
654
|
+
|
|
655
|
+
/**
|
|
656
|
+
* Generated bundle index. Do not edit.
|
|
657
|
+
*/
|
|
658
|
+
|
|
659
|
+
export { RDT_CONFIRM_DATA_LOSS_SERVICE, RDT_ROUTES_TOKEN, RdtAngularRoute, RdtConfirmDataLossService, RdtConfirmDataLossServiceAlert, RdtNavigationSource, RdtRoute, RdtRouteBuilder, RdtRouterLinkDirective, RdtRouterService };
|
|
660
|
+
//# sourceMappingURL=ngrdt-router.mjs.map
|