@singularsystems/neo-react 1.0.22 → 1.1.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/CHANGELOG.md +15 -1
- package/README.md +1 -1
- package/dist/Modules/NeoReactModule.js +1 -1
- package/dist/Modules/ReactSetup.js +1 -5
- package/dist/Modules/Types.d.ts +3 -2
- package/dist/Modules/Types.js +1 -1
- package/dist/React/ReactModelCreator.js +1 -1
- package/dist/ReactComponents/FileManager/FileInput.js +3 -1
- package/dist/ReactComponents/Form.js +3 -5
- package/dist/ReactComponents/Grid/Grid.js +7 -9
- package/dist/ReactComponents/IColorPicker.d.ts +0 -1
- package/dist/ReactComponents/Icons/IIconFactory.d.ts +0 -1
- package/dist/ReactComponents/Icons/Icon.js +1 -1
- package/dist/ReactComponents/Link.d.ts +7 -0
- package/dist/ReactComponents/Link.js +39 -6
- package/dist/ReactComponents/Modal/Modal.js +2 -2
- package/dist/ReactComponents/StateObserver.d.ts +0 -1
- package/dist/ReactComponents/Tabs/Tab.js +5 -1
- package/dist/ReactComponents/Tabs/TabContainer.d.ts +6 -2
- package/dist/ReactComponents/Tabs/TabContainer.js +25 -17
- package/dist/ReactComponents/Tabs/TabManager.d.ts +0 -12
- package/dist/ReactComponents/Tabs/TabManager.js +3 -3
- package/dist/ReactComponents/Transitions/Transition.d.ts +10 -0
- package/dist/ReactComponents/Transitions/Transition.js +13 -0
- package/dist/ReactComponents/Transitions/TransitionContainer.d.ts +22 -0
- package/dist/ReactComponents/Transitions/TransitionContainer.js +34 -0
- package/dist/ReactComponents/Transitions/TransitionController.d.ts +33 -0
- package/dist/ReactComponents/Transitions/TransitionController.js +231 -0
- package/dist/ReactComponents/Transitions/TransitionPanel.d.ts +37 -0
- package/dist/ReactComponents/Transitions/TransitionPanel.js +64 -0
- package/dist/ReactComponents/Transitions/TransitionReplacer.d.ts +15 -0
- package/dist/ReactComponents/Transitions/TransitionReplacer.js +52 -0
- package/dist/ReactComponents/Transitions/TransitionSwitcher.d.ts +15 -0
- package/dist/ReactComponents/Transitions/TransitionSwitcher.js +55 -0
- package/dist/ReactComponents/Transitions/_Exports.d.ts +2 -0
- package/dist/ReactComponents/Transitions/_Exports.js +2 -0
- package/dist/ReactComponents/_Exports.d.ts +3 -1
- package/dist/ReactComponents/_Exports.js +3 -1
- package/dist/Routing/BreadCrumbItem.d.ts +0 -1
- package/dist/Routing/IRouteChangedProps.d.ts +5 -3
- package/dist/Routing/NavigationHelper.d.ts +9 -8
- package/dist/Routing/NavigationHelper.js +121 -25
- package/dist/Routing/PageLeaveHandler.d.ts +26 -9
- package/dist/Routing/PageLeaveHandler.js +16 -39
- package/dist/Routing/RouteProvider.d.ts +28 -7
- package/dist/Routing/RouteProvider.js +81 -42
- package/dist/Routing/RouteView.d.ts +5 -27
- package/dist/Routing/RouteView.js +18 -92
- package/dist/Routing/RoutingState.d.ts +10 -13
- package/dist/Routing/RoutingState.js +35 -18
- package/dist/Routing/ViewParameter.d.ts +0 -1
- package/dist/Routing/ViewParameterList.d.ts +0 -7
- package/dist/Routing/ViewParameterList.js +4 -6
- package/dist/Views/ViewBase.d.ts +4 -4
- package/dist/Views/ViewBase.js +6 -5
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/package.json +19 -26
- package/styles/Button.scss +6 -0
- package/styles/DatePicker.scss +3 -1
- package/styles/Forms.scss +3 -1
- package/styles/Grid.scss +4 -0
- package/styles/Misc.scss +25 -0
|
@@ -1,20 +1,72 @@
|
|
|
1
|
-
import { __decorate, __metadata, __param } from "tslib";
|
|
1
|
+
import { __awaiter, __decorate, __generator, __metadata, __param } from "tslib";
|
|
2
2
|
import { ViewParameterList } from './ViewParameterList';
|
|
3
3
|
import { injectable, inject } from 'inversify';
|
|
4
4
|
import { NeoReactTypes } from '../Modules/Types';
|
|
5
5
|
import { RoutingState } from './RoutingState';
|
|
6
6
|
var NavigationHelper = /** @class */ (function () {
|
|
7
|
-
function NavigationHelper(routingState) {
|
|
7
|
+
function NavigationHelper(routingState, pageLeaveHandler) {
|
|
8
8
|
this.routingState = routingState;
|
|
9
|
+
this.pageLeaveHandler = pageLeaveHandler;
|
|
10
|
+
// PrevUrls is required since the popstate event tells you the new path, not the previous path
|
|
11
|
+
this.prevUrls = [];
|
|
12
|
+
this.isPrompting = false;
|
|
13
|
+
window.addEventListener("beforeunload", this.windowUnload.bind(this));
|
|
14
|
+
window.addEventListener("popstate", this.historyPopState.bind(this));
|
|
9
15
|
}
|
|
10
|
-
NavigationHelper.prototype.navigateInternal = function (
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
NavigationHelper.prototype.navigateInternal = function (url_1) {
|
|
17
|
+
return __awaiter(this, arguments, void 0, function (url, replace) {
|
|
18
|
+
var basePath, prevUrl, path, route, leavePrompt, canNavigate;
|
|
19
|
+
if (replace === void 0) { replace = false; }
|
|
20
|
+
return __generator(this, function (_a) {
|
|
21
|
+
switch (_a.label) {
|
|
22
|
+
case 0:
|
|
23
|
+
basePath = this.routingState.basePath;
|
|
24
|
+
prevUrl = this.prevUrls.length === 0 ? undefined : this.prevUrls[this.prevUrls.length - 1];
|
|
25
|
+
path = url;
|
|
26
|
+
if (basePath) {
|
|
27
|
+
if (path.startsWith(basePath)) {
|
|
28
|
+
path = path.substring(basePath.length);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
url = basePath + url;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (!(prevUrl !== url)) return [3 /*break*/, 5];
|
|
35
|
+
route = this.routingState.appRouteProvider.getRouteForPath(path);
|
|
36
|
+
if (!this.routingState.currentRoute) return [3 /*break*/, 4];
|
|
37
|
+
leavePrompt = this.beforeLocationChanged(route, false);
|
|
38
|
+
if (!(leavePrompt !== undefined)) return [3 /*break*/, 4];
|
|
39
|
+
_a.label = 1;
|
|
40
|
+
case 1:
|
|
41
|
+
_a.trys.push([1, , 3, 4]);
|
|
42
|
+
this.isPrompting = true;
|
|
43
|
+
return [4 /*yield*/, this.pageLeaveHandler.onLeavePage(this.routingState.currentView, leavePrompt)];
|
|
44
|
+
case 2:
|
|
45
|
+
canNavigate = _a.sent();
|
|
46
|
+
if (!canNavigate) {
|
|
47
|
+
return [2 /*return*/, false];
|
|
48
|
+
}
|
|
49
|
+
return [3 /*break*/, 4];
|
|
50
|
+
case 3:
|
|
51
|
+
this.isPrompting = false;
|
|
52
|
+
return [7 /*endfinally*/];
|
|
53
|
+
case 4:
|
|
54
|
+
if (replace) {
|
|
55
|
+
if (this.prevUrls.length > 0) {
|
|
56
|
+
this.prevUrls[this.prevUrls.length - 1] = url;
|
|
57
|
+
}
|
|
58
|
+
window.history.replaceState(null, "", url);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
this.prevUrls.push(url);
|
|
62
|
+
window.history.pushState(null, "", url);
|
|
63
|
+
}
|
|
64
|
+
this.routingState.updateRoute(route);
|
|
65
|
+
_a.label = 5;
|
|
66
|
+
case 5: return [2 /*return*/, true];
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
});
|
|
18
70
|
};
|
|
19
71
|
NavigationHelper.prototype.navigateToView = function (view, paramValues) {
|
|
20
72
|
this.navigateInternal(this.getPathForView(view, paramValues));
|
|
@@ -34,27 +86,71 @@ var NavigationHelper = /** @class */ (function () {
|
|
|
34
86
|
}
|
|
35
87
|
};
|
|
36
88
|
NavigationHelper.prototype.getCurrentViewPath = function () {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
89
|
+
if (this.routingState.currentRoute) {
|
|
90
|
+
return this.routingState.currentRoute.route.path;
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
return "";
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
NavigationHelper.prototype.historyPopState = function (e) {
|
|
97
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
98
|
+
var _a;
|
|
99
|
+
return __generator(this, function (_b) {
|
|
100
|
+
switch (_b.label) {
|
|
101
|
+
case 0:
|
|
102
|
+
_a = this.isPrompting;
|
|
103
|
+
if (_a) return [3 /*break*/, 2];
|
|
104
|
+
return [4 /*yield*/, this.navigateInternal(window.location.pathname, true)];
|
|
105
|
+
case 1:
|
|
106
|
+
_a = !(_b.sent());
|
|
107
|
+
_b.label = 2;
|
|
108
|
+
case 2:
|
|
109
|
+
if (_a) {
|
|
110
|
+
// cancel navigation by pushing the previous state back into history.
|
|
111
|
+
window.history.pushState(null, "", this.prevUrls[this.prevUrls.length - 1]);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
// remove our state to match browsers state.
|
|
115
|
+
this.prevUrls.pop();
|
|
116
|
+
}
|
|
117
|
+
return [2 /*return*/];
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
};
|
|
122
|
+
NavigationHelper.prototype.windowUnload = function (e) {
|
|
123
|
+
var leavePrompt = this.beforeLocationChanged(null, true);
|
|
124
|
+
if (leavePrompt !== undefined) {
|
|
125
|
+
this.pageLeaveHandler.onWindowUnload(this.routingState.currentView, leavePrompt, e);
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
NavigationHelper.prototype.beforeLocationChanged = function (newRoute, isUnload) {
|
|
129
|
+
var _a;
|
|
130
|
+
var currentRoute = this.routingState.currentRoute;
|
|
131
|
+
var changeProps = {
|
|
132
|
+
isNewView: !currentRoute || currentRoute.route !== (newRoute === null || newRoute === void 0 ? void 0 : newRoute.route),
|
|
133
|
+
isUnload: isUnload !== null && isUnload !== void 0 ? isUnload : false,
|
|
134
|
+
currentView: (_a = this.routingState.currentView) !== null && _a !== void 0 ? _a : undefined,
|
|
135
|
+
newRoute: newRoute === null || newRoute === void 0 ? void 0 : newRoute.route,
|
|
136
|
+
params: newRoute === null || newRoute === void 0 ? void 0 : newRoute.params
|
|
137
|
+
};
|
|
138
|
+
if (this.routingState.currentView) {
|
|
139
|
+
this.routingState.currentView.beforeRouteChanged(changeProps);
|
|
140
|
+
if (changeProps.leavePrompt === undefined && (changeProps.isNewView || changeProps.isUnload)) {
|
|
141
|
+
changeProps.leavePrompt = this.routingState.currentView.onLeave();
|
|
43
142
|
}
|
|
44
143
|
}
|
|
45
|
-
|
|
144
|
+
if (changeProps.isNewView) {
|
|
145
|
+
this.pageLeaveHandler.beforeLeavePage(changeProps);
|
|
146
|
+
}
|
|
147
|
+
return changeProps.leavePrompt;
|
|
46
148
|
};
|
|
47
|
-
Object.defineProperty(NavigationHelper.prototype, "currentRouteProps", {
|
|
48
|
-
get: function () {
|
|
49
|
-
return this.routingState.currentRouteProps;
|
|
50
|
-
},
|
|
51
|
-
enumerable: false,
|
|
52
|
-
configurable: true
|
|
53
|
-
});
|
|
54
149
|
NavigationHelper = __decorate([
|
|
55
150
|
injectable(),
|
|
56
151
|
__param(0, inject(NeoReactTypes.Routing.GlobalRoutingState.symbol)),
|
|
57
|
-
|
|
152
|
+
__param(1, inject(NeoReactTypes.Routing.PageLeaveHandler.symbol)),
|
|
153
|
+
__metadata("design:paramtypes", [RoutingState, Object])
|
|
58
154
|
], NavigationHelper);
|
|
59
155
|
return NavigationHelper;
|
|
60
156
|
}());
|
|
@@ -1,13 +1,30 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Views } from '@singularsystems/neo-core';
|
|
2
2
|
import { RoutingState } from './RoutingState';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import { IViewBase } from "../Views/ViewBase";
|
|
4
|
+
import { IRouteChangedProps, RouteChangedLeavePrompt } from "./IRouteChangedProps";
|
|
5
|
+
export interface IPageLeaveHandler {
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
* Called after `ViewBase.beforeRouteChanged` and `ViewBase.onLeave` are called.
|
|
8
|
+
* @param changeProps
|
|
8
9
|
*/
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
beforeLeavePage(changeProps: IRouteChangedProps): void;
|
|
11
|
+
/**
|
|
12
|
+
* Called when the user tries to leave the page, and the page / leave handler has indicated the user must be prompted.
|
|
13
|
+
* @returns A boolean promise with a value indicating whether the user wants to leave the page.
|
|
14
|
+
*/
|
|
15
|
+
onLeavePage(view: Views.IViewBase | null, leavePrompt: RouteChangedLeavePrompt): Promise<boolean>;
|
|
16
|
+
/**
|
|
17
|
+
* Called when the windows beforeunload event fires, and the page / leave handler has indicated the user must be prompted.
|
|
18
|
+
* @param view The currently active view.
|
|
19
|
+
* @param e beforeunload event.
|
|
20
|
+
*/
|
|
21
|
+
onWindowUnload(view: IViewBase | null, leavePrompt: RouteChangedLeavePrompt, e: BeforeUnloadEvent): void;
|
|
22
|
+
}
|
|
23
|
+
export declare class PageLeaveHandler implements IPageLeaveHandler {
|
|
24
|
+
private routingState;
|
|
25
|
+
constructor(routingState: RoutingState);
|
|
26
|
+
beforeLeavePage(changeProps: IRouteChangedProps): void;
|
|
27
|
+
onLeavePage(view: Views.IViewBase | null, leavePrompt: RouteChangedLeavePrompt): Promise<boolean>;
|
|
28
|
+
onWindowUnload(view: Views.IViewBase | null, leavePrompt: RouteChangedLeavePrompt, e: BeforeUnloadEvent): void;
|
|
29
|
+
protected showDefaultConfirmation(view: Views.IViewBase | null, prompt: string): Promise<boolean>;
|
|
13
30
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { __awaiter, __decorate, __generator, __metadata, __param } from "tslib";
|
|
2
|
-
import {
|
|
2
|
+
import { ModalUtils, Misc } from '@singularsystems/neo-core';
|
|
3
3
|
import { inject, injectable } from 'inversify';
|
|
4
4
|
import { NeoReactTypes } from '../Modules/Types';
|
|
5
5
|
import { RoutingState } from './RoutingState';
|
|
@@ -7,55 +7,32 @@ var PageLeaveHandler = /** @class */ (function () {
|
|
|
7
7
|
function PageLeaveHandler(routingState) {
|
|
8
8
|
this.routingState = routingState;
|
|
9
9
|
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
PageLeaveHandler.showNavigationConfirmation = function (prompt, callback) {
|
|
10
|
+
PageLeaveHandler.prototype.beforeLeavePage = function (changeProps) {
|
|
11
|
+
};
|
|
12
|
+
PageLeaveHandler.prototype.onLeavePage = function (view, leavePrompt) {
|
|
14
13
|
return __awaiter(this, void 0, void 0, function () {
|
|
15
|
-
var
|
|
14
|
+
var result;
|
|
16
15
|
return __generator(this, function (_a) {
|
|
17
16
|
switch (_a.label) {
|
|
18
17
|
case 0:
|
|
19
|
-
|
|
20
|
-
return [
|
|
18
|
+
if (!(leavePrompt === false)) return [3 /*break*/, 1];
|
|
19
|
+
return [2 /*return*/, Promise.resolve(false)];
|
|
21
20
|
case 1:
|
|
21
|
+
if (!(typeof leavePrompt === "string")) return [3 /*break*/, 2];
|
|
22
|
+
return [2 /*return*/, this.showDefaultConfirmation(view, leavePrompt)];
|
|
23
|
+
case 2: return [4 /*yield*/, leavePrompt];
|
|
24
|
+
case 3:
|
|
22
25
|
result = _a.sent();
|
|
23
|
-
|
|
24
|
-
return [2 /*return*/];
|
|
26
|
+
return [2 /*return*/, result === true || result === Misc.ModalResult.Yes];
|
|
25
27
|
}
|
|
26
28
|
});
|
|
27
29
|
});
|
|
28
30
|
};
|
|
29
|
-
PageLeaveHandler.prototype.onWindowUnload = function (view, e) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
var prompt_1 = routeView.beforeLocationChanged(undefined, "PUSH", true);
|
|
33
|
-
if (prompt_1 || prompt_1 === false || prompt_1 === "") {
|
|
34
|
-
e.preventDefault();
|
|
35
|
-
e.returnValue = !prompt_1 ? "Are you sure you want to continue?" : prompt_1;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
PageLeaveHandler.prototype.onLeavePage = function (view, prompt, location) {
|
|
40
|
-
if (this.routingState.leavePromise) {
|
|
41
|
-
var promise_1 = this.routingState.leavePromise;
|
|
42
|
-
this.routingState.leavePromise = undefined;
|
|
43
|
-
return new Promise(function (resolve) {
|
|
44
|
-
promise_1.then(function (result) {
|
|
45
|
-
if (result) {
|
|
46
|
-
resolve(result === true || result === Misc.ModalResult.Yes);
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
49
|
-
resolve(false);
|
|
50
|
-
}
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
return this.showDefaultConfirmation(view, prompt, location);
|
|
56
|
-
}
|
|
31
|
+
PageLeaveHandler.prototype.onWindowUnload = function (view, leavePrompt, e) {
|
|
32
|
+
e.preventDefault();
|
|
33
|
+
e.returnValue = typeof leavePrompt === "string" ? leavePrompt : "Are you sure you want to continue?";
|
|
57
34
|
};
|
|
58
|
-
PageLeaveHandler.prototype.showDefaultConfirmation = function (view, prompt
|
|
35
|
+
PageLeaveHandler.prototype.showDefaultConfirmation = function (view, prompt) {
|
|
59
36
|
var title = view ? view.viewName : "Un-saved Changes";
|
|
60
37
|
return new Promise(function (resolve) {
|
|
61
38
|
ModalUtils.showModal(title, prompt, {
|
|
@@ -1,25 +1,45 @@
|
|
|
1
1
|
import { Routing } from '@singularsystems/neo-core';
|
|
2
2
|
import React from 'react';
|
|
3
|
+
import { IRouteParameter } from "./IRouteParameter";
|
|
4
|
+
interface INamedRouteParameter extends IRouteParameter {
|
|
5
|
+
name: string;
|
|
6
|
+
}
|
|
3
7
|
export interface IProcessedRoute extends Routing.IRoute {
|
|
4
8
|
key: number;
|
|
5
|
-
/**
|
|
6
|
-
|
|
9
|
+
/** Lower case base path without trailing / */
|
|
10
|
+
path: string;
|
|
11
|
+
/** Route params in order, excluding query parameters. */
|
|
12
|
+
params: INamedRouteParameter[];
|
|
13
|
+
}
|
|
14
|
+
type ParamsObject = {
|
|
15
|
+
[index: string]: string | undefined;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* A route which has matched, with its parameter values populated from the path.
|
|
19
|
+
*/
|
|
20
|
+
export interface IMatchedRoute {
|
|
21
|
+
route: IProcessedRoute;
|
|
22
|
+
/** Path used for the route match. Including parameter path values. Will not include the query string. */
|
|
23
|
+
path: string;
|
|
24
|
+
/** Param values matched from the path. */
|
|
25
|
+
params?: ParamsObject;
|
|
7
26
|
}
|
|
8
27
|
export default class RouteProvider {
|
|
9
28
|
menuRoutes: Routing.IMenuRoute[];
|
|
10
29
|
pureRoutes?: Routing.IRoute[] | undefined;
|
|
11
|
-
|
|
30
|
+
notFoundComponent?: React.ComponentType | undefined;
|
|
12
31
|
private key;
|
|
13
32
|
private routeIndex;
|
|
14
|
-
private
|
|
15
|
-
|
|
33
|
+
private staticRoutes;
|
|
34
|
+
private parameterisedRoutes;
|
|
35
|
+
readonly allRoutes: IProcessedRoute[];
|
|
16
36
|
/**
|
|
17
37
|
* Creates a route provider which provides a list of flattened routes.
|
|
18
38
|
* @param menuRoutes Routes which appear on the main menu.
|
|
19
39
|
* @param pureRoutes Routes which don't have a menu item.
|
|
20
|
-
* @param
|
|
40
|
+
* @param notFoundComponent Component to render when the url doesn't match any of the above routes.
|
|
21
41
|
*/
|
|
22
|
-
constructor(menuRoutes: Routing.IMenuRoute[], pureRoutes?: Routing.IRoute[] | undefined,
|
|
42
|
+
constructor(menuRoutes: Routing.IMenuRoute[], pureRoutes?: Routing.IRoute[] | undefined, notFoundComponent?: React.ComponentType | undefined);
|
|
23
43
|
/** Gets the path the component is bound to. If the component is bound to multiple paths, the first path is returned. */
|
|
24
44
|
getPathForComponent(component: any): string | undefined;
|
|
25
45
|
private flatten;
|
|
@@ -29,3 +49,4 @@ export default class RouteProvider {
|
|
|
29
49
|
*/
|
|
30
50
|
private processRoute;
|
|
31
51
|
}
|
|
52
|
+
export {};
|
|
@@ -5,39 +5,85 @@ var RouteProvider = /** @class */ (function () {
|
|
|
5
5
|
* Creates a route provider which provides a list of flattened routes.
|
|
6
6
|
* @param menuRoutes Routes which appear on the main menu.
|
|
7
7
|
* @param pureRoutes Routes which don't have a menu item.
|
|
8
|
-
* @param
|
|
8
|
+
* @param notFoundComponent Component to render when the url doesn't match any of the above routes.
|
|
9
9
|
*/
|
|
10
|
-
function RouteProvider(menuRoutes, pureRoutes,
|
|
11
|
-
var _a;
|
|
10
|
+
function RouteProvider(menuRoutes, pureRoutes, notFoundComponent) {
|
|
12
11
|
this.menuRoutes = menuRoutes;
|
|
13
12
|
this.pureRoutes = pureRoutes;
|
|
14
|
-
this.
|
|
13
|
+
this.notFoundComponent = notFoundComponent;
|
|
15
14
|
this.key = 1;
|
|
16
15
|
this.routeIndex = {};
|
|
17
|
-
this.
|
|
18
|
-
this.
|
|
19
|
-
this.
|
|
16
|
+
this.staticRoutes = [];
|
|
17
|
+
this.parameterisedRoutes = [];
|
|
18
|
+
this.allRoutes = [];
|
|
19
|
+
this.flatten(this.allRoutes, menuRoutes);
|
|
20
20
|
if (pureRoutes)
|
|
21
|
-
this.flatten(pureRoutes);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
/
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
If the above was swapped around, ClientsComponent would match instead of SubViewComponent for /clients/subview.
|
|
29
|
-
*/
|
|
30
|
-
(_a = this.flattenedRoutes).push.apply(_a, this.paramRoutes.sortBy("order", "desc").map(function (c) { return c.route; }));
|
|
31
|
-
if (notFoundRoute) {
|
|
32
|
-
this.flattenedRoutes.push({ component: notFoundRoute, key: -1, allowAnonymous: true, routePath: "" });
|
|
33
|
-
}
|
|
21
|
+
this.flatten(this.allRoutes, pureRoutes);
|
|
22
|
+
this.staticRoutes = this.allRoutes.filter(function (c) { return c.params.length === 0; });
|
|
23
|
+
this.parameterisedRoutes = this.allRoutes
|
|
24
|
+
.filter(function (c) { return c.params.length > 0; })
|
|
25
|
+
.map(function (route) { return ({ route: route, order: route.path.split("/").length }); })
|
|
26
|
+
.sortBy(function (c) { return c.order; }, "desc")
|
|
27
|
+
.map(function (c) { return c.route; });
|
|
34
28
|
}
|
|
35
29
|
/** Gets the path the component is bound to. If the component is bound to multiple paths, the first path is returned. */
|
|
36
30
|
RouteProvider.prototype.getPathForComponent = function (component) {
|
|
37
31
|
var _a;
|
|
38
|
-
return (_a = this.
|
|
32
|
+
return (_a = this.allRoutes.find(function (c) { return c.component === component; })) === null || _a === void 0 ? void 0 : _a.path;
|
|
33
|
+
};
|
|
34
|
+
/** @internal */
|
|
35
|
+
RouteProvider.prototype.getRouteForPath = function (path) {
|
|
36
|
+
return RouteProvider.getRouteForPath(this.staticRoutes, this.parameterisedRoutes, path);
|
|
39
37
|
};
|
|
40
|
-
|
|
38
|
+
/** @internal */
|
|
39
|
+
RouteProvider.getRouteForPath = function (staticRoutes, parameterisedRoutes, path) {
|
|
40
|
+
var queryIndex = path.indexOf("?");
|
|
41
|
+
if (queryIndex >= 0) {
|
|
42
|
+
path = path.substring(0, queryIndex);
|
|
43
|
+
}
|
|
44
|
+
var lcPath = path.toLowerCase();
|
|
45
|
+
var found = staticRoutes.find(function (route) { return route.path === lcPath; });
|
|
46
|
+
if (found) {
|
|
47
|
+
return { route: found, path: path };
|
|
48
|
+
}
|
|
49
|
+
if (path.endsWith("/")) {
|
|
50
|
+
// special case for where an extra "/" is added to the url by mistake.
|
|
51
|
+
var trimmedPath_1 = lcPath.substring(0, path.length - 1);
|
|
52
|
+
var found_1 = staticRoutes.find(function (route) { return route.path === trimmedPath_1; });
|
|
53
|
+
if (found_1) {
|
|
54
|
+
return { route: found_1, path: path };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
var matches = parameterisedRoutes.filter(function (route) { return lcPath.startsWith(route.path); });
|
|
58
|
+
for (var _i = 0, matches_1 = matches; _i < matches_1.length; _i++) {
|
|
59
|
+
var match = matches_1[_i];
|
|
60
|
+
var paramString = path.substring(match.path.length);
|
|
61
|
+
var parts = paramString.split("/").slice(1);
|
|
62
|
+
var partCount = parts.length;
|
|
63
|
+
// Allow extra "/"
|
|
64
|
+
if (partCount > 0 && parts[partCount - 1] === "") {
|
|
65
|
+
partCount -= 1;
|
|
66
|
+
}
|
|
67
|
+
if (match.params.length >= partCount) {
|
|
68
|
+
var paramValues = {};
|
|
69
|
+
var isValid = true;
|
|
70
|
+
for (var i = 0; i < match.params.length; i++) {
|
|
71
|
+
var param = match.params[i];
|
|
72
|
+
var value = parts[i];
|
|
73
|
+
paramValues[param.name] = value;
|
|
74
|
+
if (param.required && !value) {
|
|
75
|
+
isValid = false;
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (isValid) {
|
|
80
|
+
return { route: match, path: path, params: paramValues };
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return null;
|
|
85
|
+
};
|
|
86
|
+
RouteProvider.prototype.flatten = function (into, routes, parent) {
|
|
41
87
|
var _a, _b;
|
|
42
88
|
for (var _i = 0, routes_1 = routes; _i < routes_1.length; _i++) {
|
|
43
89
|
var route = routes_1[_i];
|
|
@@ -46,45 +92,38 @@ var RouteProvider = /** @class */ (function () {
|
|
|
46
92
|
if (parent && !route.breadCrumbParent) {
|
|
47
93
|
route.breadCrumbParent = parent;
|
|
48
94
|
}
|
|
49
|
-
this.processRoute(route);
|
|
95
|
+
this.processRoute(into, route);
|
|
50
96
|
}
|
|
51
97
|
var menuRoute = route;
|
|
52
98
|
var children = __spreadArray(__spreadArray([], ((_a = route.routeChildren) !== null && _a !== void 0 ? _a : []), true), ((_b = menuRoute.children) !== null && _b !== void 0 ? _b : []), true);
|
|
53
|
-
this.flatten(children, (hasComponent && menuRoute.showInBreadCrumb !== false) ? menuRoute : undefined);
|
|
99
|
+
this.flatten(into, children, (hasComponent && menuRoute.showInBreadCrumb !== false) ? menuRoute : undefined);
|
|
54
100
|
}
|
|
55
101
|
};
|
|
56
102
|
/**
|
|
57
103
|
* Create a copy of the route info, and process it.
|
|
58
104
|
* Adds a unique key, and adds route parameters extracted from the component static params object.
|
|
59
105
|
*/
|
|
60
|
-
RouteProvider.prototype.processRoute = function (route) {
|
|
61
|
-
var processed = __assign(__assign({}, route), {
|
|
62
|
-
var isParamRoute = false;
|
|
106
|
+
RouteProvider.prototype.processRoute = function (into, route) {
|
|
107
|
+
var processed = __assign(__assign({}, route), { path: route.path, params: [], key: this.key++ });
|
|
63
108
|
if (route instanceof MenuRoute) {
|
|
64
|
-
processed.
|
|
109
|
+
processed.path = route.basePath;
|
|
110
|
+
}
|
|
111
|
+
processed.path = processed.path.toLowerCase();
|
|
112
|
+
if (processed.path.length > 1 && processed.path.endsWith("/")) {
|
|
113
|
+
processed.path = processed.path.substring(0, processed.path.length - 1);
|
|
65
114
|
}
|
|
66
115
|
var viewBaseComponent = route.component;
|
|
67
116
|
if (viewBaseComponent.params) {
|
|
68
|
-
if (processed.routePath.endsWith("/")) {
|
|
69
|
-
processed.routePath = processed.routePath.substring(0, processed.routePath.length - 1);
|
|
70
|
-
}
|
|
71
117
|
for (var param in viewBaseComponent.params) {
|
|
72
118
|
var routeParam = viewBaseComponent.params[param];
|
|
73
119
|
if (!routeParam.isQuery) {
|
|
74
|
-
|
|
75
|
-
processed.routePath += "/:" + param + (routeParam.required ? "" : "?");
|
|
120
|
+
processed.params.push(__assign(__assign({}, routeParam), { name: param }));
|
|
76
121
|
}
|
|
77
122
|
}
|
|
78
123
|
}
|
|
79
|
-
if (!this.routeIndex[processed.
|
|
80
|
-
this.routeIndex[processed.
|
|
81
|
-
|
|
82
|
-
// Must be ordered later by the number of slashes in the path. Root path is a special case.
|
|
83
|
-
this.paramRoutes.push({ route: processed, order: route.path === "/" ? 0 : (route.path.match(/\//g) || []).length });
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
this.flattenedRoutes.push(processed);
|
|
87
|
-
}
|
|
124
|
+
if (!this.routeIndex[processed.path]) {
|
|
125
|
+
this.routeIndex[processed.path] = true;
|
|
126
|
+
into.push(processed);
|
|
88
127
|
}
|
|
89
128
|
};
|
|
90
129
|
return RouteProvider;
|
|
@@ -1,40 +1,18 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { RouteComponentProps, Switch, Route } from 'react-router';
|
|
3
|
-
import { Location, Action } from 'history';
|
|
4
2
|
import { Routing } from '@singularsystems/neo-core';
|
|
5
3
|
import RouteProvider from './RouteProvider';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}
|
|
10
|
-
export default abstract class RouteView extends React.Component<RouteComponentProps> {
|
|
11
|
-
private historyListenDisposer?;
|
|
12
|
-
private historyBlockDisposer?;
|
|
13
|
-
protected switchComponent: typeof Switch;
|
|
14
|
-
protected routeComponent: typeof Route;
|
|
4
|
+
export default abstract class RouteView extends React.Component<unknown> {
|
|
5
|
+
private routeProvider;
|
|
6
|
+
private hasMounted;
|
|
15
7
|
protected _routes: RouteProvider;
|
|
16
8
|
protected getForbiddenComponent: (route: Routing.IRoute) => JSX.Element;
|
|
17
9
|
protected getSigningInComponent: (route: Routing.IRoute) => JSX.Element;
|
|
18
10
|
protected securityService: import("@singularsystems/neo-core/dist/Security/ISecurityService").default;
|
|
19
11
|
protected routeSecurityService: Routing.IRouteSecurityService;
|
|
20
12
|
protected routingState: import("./RoutingState").RoutingState;
|
|
21
|
-
constructor(props:
|
|
22
|
-
get routes(): RouteProvider;
|
|
23
|
-
set routes(value: RouteProvider);
|
|
13
|
+
constructor(props: unknown, routeProvider: RouteProvider);
|
|
24
14
|
componentDidMount(): void;
|
|
25
|
-
|
|
26
|
-
componentWillUnmount(): void;
|
|
27
|
-
private beforeLocationChanged;
|
|
28
|
-
/**
|
|
29
|
-
* Called when the url changes, before the router renders the new view.
|
|
30
|
-
* Return a string to block navigation.
|
|
31
|
-
* @param isNewView True if the view is changing. False if a view parameter value is changing.
|
|
32
|
-
* @param currentView The current view before change.
|
|
33
|
-
*/
|
|
34
|
-
protected beforeRouteChanged(props: IRouteChangedProps): void;
|
|
35
|
-
private getMatch;
|
|
36
|
-
static isExact(route: Routing.IRoute): boolean;
|
|
37
|
-
render(): React.CElement<import("react-router").SwitchProps, Switch>;
|
|
15
|
+
render(): JSX.Element | null;
|
|
38
16
|
private getRouteComponent;
|
|
39
17
|
/**
|
|
40
18
|
* Creates the routes component after authentication and authorisation checks have been done.
|