@singularsystems/neo-react 1.5.0 → 1.6.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 +7 -0
- package/dist/ReactComponents/Link.d.ts +1 -0
- package/dist/ReactComponents/Link.js +17 -10
- package/dist/Routing/IRouteParameter.d.ts +4 -0
- package/dist/Routing/MenuRoute.d.ts +11 -6
- package/dist/Routing/MenuRoute.js +31 -10
- package/dist/Routing/NavigationHelper.d.ts +1 -4
- package/dist/Routing/NavigationHelper.js +5 -10
- package/dist/Routing/RouteHelper.d.ts +8 -0
- package/dist/Routing/RouteHelper.js +54 -0
- package/dist/Routing/RouteProvider.d.ts +16 -7
- package/dist/Routing/RouteProvider.js +114 -64
- package/dist/Routing/ViewParameter.d.ts +9 -14
- package/dist/Routing/ViewParameter.js +7 -36
- package/dist/Routing/ViewParameterList.d.ts +14 -28
- package/dist/Routing/ViewParameterList.js +71 -115
- package/dist/Views/ViewBase.js +3 -4
- package/package.json +2 -2
- package/styles/Forms.scss +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
This file details all new features and changes to functionality. If you only need to see changes that require updates to your project, see the [breaking changes](./Breaking.md) readme.
|
|
4
4
|
|
|
5
|
+
## Version 1.6.1 (23 June 2026)
|
|
6
|
+
|
|
7
|
+
- Routing changes
|
|
8
|
+
- Routes parameters can now be defined in the route path. E.g. `/products/:id/sales`.
|
|
9
|
+
- Parameters not defined in the path will continue to be appended at the end of the path.
|
|
10
|
+
- Internal overhaul of routing system to allow better unit testing.
|
|
11
|
+
|
|
5
12
|
## Version 1.5.0 (28 May 2026)
|
|
6
13
|
|
|
7
14
|
- Fixed routes with the same prefix, but different parameter counts not being registered.
|
|
@@ -15,6 +15,7 @@ var Link = /** @class */ (function (_super) {
|
|
|
15
15
|
_this.basePath = Misc.Globals.appService.get(NeoReactTypes.Routing.GlobalRoutingState).basePath;
|
|
16
16
|
return _this;
|
|
17
17
|
}
|
|
18
|
+
Link_1 = Link;
|
|
18
19
|
Link.prototype.onClick = function (e) {
|
|
19
20
|
if (this.props.onClick) {
|
|
20
21
|
this.props.onClick(e);
|
|
@@ -37,22 +38,28 @@ var Link = /** @class */ (function (_super) {
|
|
|
37
38
|
if (isNav) {
|
|
38
39
|
// Cause re-render if current route changes.
|
|
39
40
|
void Misc.Globals.appService.get(NeoReactTypes.Routing.GlobalRoutingState).currentRoute;
|
|
40
|
-
|
|
41
|
-
var toLc = to.toLowerCase();
|
|
42
|
-
if (path.endsWith("/")) {
|
|
43
|
-
path = path.substring(0, path.length - 1);
|
|
44
|
-
}
|
|
45
|
-
var isMatch = exact === true ?
|
|
46
|
-
toLc === path :
|
|
47
|
-
path.startsWith(toLc);
|
|
48
|
-
if (isMatch) {
|
|
41
|
+
if (Link_1.isMatch(to, window.location.pathname, exact)) {
|
|
49
42
|
rest.className = Utils.joinWithSpaces(rest.className, "active");
|
|
50
43
|
}
|
|
51
44
|
}
|
|
52
45
|
}
|
|
53
46
|
return React.createElement("a", __assign({}, rest, { href: href, onClick: this.onClick }), this.props.children);
|
|
54
47
|
};
|
|
55
|
-
Link =
|
|
48
|
+
Link.isMatch = function (linkPath, currentPath, exact) {
|
|
49
|
+
linkPath = linkPath.toLowerCase();
|
|
50
|
+
currentPath = currentPath.toLowerCase();
|
|
51
|
+
if (!currentPath.endsWith("/")) {
|
|
52
|
+
currentPath += "/";
|
|
53
|
+
}
|
|
54
|
+
if (!linkPath.endsWith("/")) {
|
|
55
|
+
linkPath += "/";
|
|
56
|
+
}
|
|
57
|
+
return exact === true ?
|
|
58
|
+
linkPath === currentPath :
|
|
59
|
+
currentPath.startsWith(linkPath);
|
|
60
|
+
};
|
|
61
|
+
var Link_1;
|
|
62
|
+
Link = Link_1 = __decorate([
|
|
56
63
|
observer,
|
|
57
64
|
__metadata("design:paramtypes", [Object])
|
|
58
65
|
], Link);
|
|
@@ -20,3 +20,7 @@ export type RouteParameters = {
|
|
|
20
20
|
export type RouteParameterObject<T> = {
|
|
21
21
|
[P in keyof T]: IRouteParameter;
|
|
22
22
|
};
|
|
23
|
+
export type ValidParameterValue = number | string | string[] | null;
|
|
24
|
+
export type ParamValues<TParams> = {
|
|
25
|
+
[P in keyof TParams]?: ValidParameterValue;
|
|
26
|
+
};
|
|
@@ -2,8 +2,16 @@ import ViewBase from '../Views/ViewBase';
|
|
|
2
2
|
import { Routing } from '@singularsystems/neo-core';
|
|
3
3
|
import { RouteParameterObject } from './IRouteParameter';
|
|
4
4
|
export interface IMenuRoute extends Routing.IMenuRoute {
|
|
5
|
+
/** The base route. Can be used instead of specifying path */
|
|
6
|
+
baseRoute?: Routing.IRoute;
|
|
5
7
|
}
|
|
6
8
|
export declare class MenuRoute<TParams extends RouteParameterObject<TParams>> implements IMenuRoute {
|
|
9
|
+
baseRoute: {
|
|
10
|
+
path: string;
|
|
11
|
+
component: new (...args: any) => ViewBase<any, TParams>;
|
|
12
|
+
};
|
|
13
|
+
private viewParamValues?;
|
|
14
|
+
private _path?;
|
|
7
15
|
/**
|
|
8
16
|
* Creates a menu route with view parameters specified.
|
|
9
17
|
* @param baseRoute Path and component
|
|
@@ -13,13 +21,10 @@ export declare class MenuRoute<TParams extends RouteParameterObject<TParams>> im
|
|
|
13
21
|
constructor(baseRoute: {
|
|
14
22
|
path: string;
|
|
15
23
|
component: new (...args: any) => ViewBase<any, TParams>;
|
|
16
|
-
}, menuParams: Routing.IMenuRoute,
|
|
17
|
-
[P in keyof TParams]?: number | string | null;
|
|
18
|
-
});
|
|
24
|
+
}, menuParams: Routing.IMenuRoute, viewParamValues?: { [P in keyof TParams]?: number | string | null; } | undefined);
|
|
19
25
|
/** Path including view param values. */
|
|
20
|
-
path: string;
|
|
21
|
-
/** Path without parameter values or routing template. */
|
|
22
|
-
basePath: string;
|
|
26
|
+
get path(): string;
|
|
23
27
|
/** Name to show in the menu item. */
|
|
24
28
|
name: string;
|
|
29
|
+
clone(): IMenuRoute;
|
|
25
30
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { __assign } from "tslib";
|
|
2
|
+
import { RouteHelper } from "./RouteHelper";
|
|
3
|
+
import RouteProvider from "./RouteProvider";
|
|
2
4
|
var MenuRoute = /** @class */ (function () {
|
|
3
5
|
/**
|
|
4
6
|
* Creates a menu route with view parameters specified.
|
|
@@ -6,21 +8,40 @@ var MenuRoute = /** @class */ (function () {
|
|
|
6
8
|
* @param menuParams Other menu options.
|
|
7
9
|
* @param viewParams View parameter values.
|
|
8
10
|
*/
|
|
9
|
-
function MenuRoute(baseRoute, menuParams,
|
|
11
|
+
function MenuRoute(baseRoute, menuParams, viewParamValues) {
|
|
10
12
|
var _this = this;
|
|
13
|
+
this.baseRoute = baseRoute;
|
|
14
|
+
this.viewParamValues = viewParamValues;
|
|
11
15
|
Object.getOwnPropertyNames(baseRoute).forEach(function (propertyName) {
|
|
12
|
-
|
|
13
|
-
|
|
16
|
+
if (propertyName !== "path") {
|
|
17
|
+
// @ts-ignore
|
|
18
|
+
_this[propertyName] = baseRoute[propertyName];
|
|
19
|
+
}
|
|
14
20
|
});
|
|
15
21
|
Object.getOwnPropertyNames(menuParams).forEach(function (propertyName) {
|
|
16
|
-
|
|
17
|
-
|
|
22
|
+
if (propertyName !== "path") {
|
|
23
|
+
// @ts-ignore
|
|
24
|
+
_this[propertyName] = menuParams[propertyName];
|
|
25
|
+
}
|
|
18
26
|
});
|
|
19
|
-
this.basePath = this.path;
|
|
20
|
-
if (viewParams) {
|
|
21
|
-
this.path = ViewParameterList.getPathForValues(this.basePath, baseRoute.component.params, viewParams);
|
|
22
|
-
}
|
|
23
27
|
}
|
|
28
|
+
Object.defineProperty(MenuRoute.prototype, "path", {
|
|
29
|
+
/** Path including view param values. */
|
|
30
|
+
get: function () {
|
|
31
|
+
if (!this._path) {
|
|
32
|
+
var processedRoute = RouteProvider.getProcessedRoute(this.baseRoute);
|
|
33
|
+
this._path = RouteHelper.hydrateRoute(processedRoute, this.viewParamValues);
|
|
34
|
+
}
|
|
35
|
+
return this._path;
|
|
36
|
+
},
|
|
37
|
+
enumerable: false,
|
|
38
|
+
configurable: true
|
|
39
|
+
});
|
|
40
|
+
MenuRoute.prototype.clone = function () {
|
|
41
|
+
var clone = __assign({}, this);
|
|
42
|
+
clone.path = this.path;
|
|
43
|
+
return clone;
|
|
44
|
+
};
|
|
24
45
|
return MenuRoute;
|
|
25
46
|
}());
|
|
26
47
|
export { MenuRoute };
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import ViewBase from '../Views/ViewBase';
|
|
2
2
|
import { RoutingState } from './RoutingState';
|
|
3
3
|
import { INavigationHelper as INeoNavigationHelper } from '@singularsystems/neo-core/dist/Routing/INavigationHelper';
|
|
4
|
-
import { RouteParameterObject } from './IRouteParameter';
|
|
4
|
+
import { ParamValues, RouteParameterObject } from './IRouteParameter';
|
|
5
5
|
import type { IPageLeaveHandler } from "./PageLeaveHandler";
|
|
6
6
|
export type ViewConstructor<TParams extends RouteParameterObject<TParams>> = new (...args: any) => ViewBase<any, TParams>;
|
|
7
|
-
export type ParamValues<TParams> = {
|
|
8
|
-
[P in keyof TParams]?: number | string | null;
|
|
9
|
-
};
|
|
10
7
|
export interface INavigationHelper extends INeoNavigationHelper {
|
|
11
8
|
/**
|
|
12
9
|
* Navigates to the view, if the view component is found in the routes definition.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { __awaiter, __decorate, __generator, __metadata, __param } from "tslib";
|
|
2
|
-
import { ViewParameterList } from './ViewParameterList';
|
|
3
2
|
import { injectable, inject } from 'inversify';
|
|
4
3
|
import { NeoReactTypes } from '../Modules/Types';
|
|
5
4
|
import { RoutingState } from './RoutingState';
|
|
5
|
+
import { RouteHelper } from "./RouteHelper";
|
|
6
6
|
var NavigationHelper = /** @class */ (function () {
|
|
7
7
|
function NavigationHelper(routingState, pageLeaveHandler) {
|
|
8
8
|
this.routingState = routingState;
|
|
@@ -98,14 +98,9 @@ var NavigationHelper = /** @class */ (function () {
|
|
|
98
98
|
return openerState;
|
|
99
99
|
};
|
|
100
100
|
NavigationHelper.prototype.getPathForView = function (view, paramValues) {
|
|
101
|
-
var
|
|
102
|
-
if (
|
|
103
|
-
|
|
104
|
-
return ViewParameterList.getPathForValues(basePath, view.params, paramValues);
|
|
105
|
-
}
|
|
106
|
-
else {
|
|
107
|
-
return basePath;
|
|
108
|
-
}
|
|
101
|
+
var route = this.routingState.appRouteProvider.getRouteForComponent(view);
|
|
102
|
+
if (route !== undefined) {
|
|
103
|
+
return RouteHelper.hydrateRoute(route, paramValues);
|
|
109
104
|
}
|
|
110
105
|
else {
|
|
111
106
|
throw Error("Cannot find route for component " + view.name);
|
|
@@ -113,7 +108,7 @@ var NavigationHelper = /** @class */ (function () {
|
|
|
113
108
|
};
|
|
114
109
|
NavigationHelper.prototype.getCurrentViewPath = function () {
|
|
115
110
|
if (this.routingState.currentRoute) {
|
|
116
|
-
return this.routingState.currentRoute.route.
|
|
111
|
+
return this.routingState.currentRoute.route.defaultPath;
|
|
117
112
|
}
|
|
118
113
|
else {
|
|
119
114
|
return "";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ParamValues, ValidParameterValue } from "./IRouteParameter";
|
|
2
|
+
import { IProcessedRoute } from "./RouteProvider";
|
|
3
|
+
export declare class RouteHelper {
|
|
4
|
+
/** Populates the route's path with the provided parameter values. */
|
|
5
|
+
static hydrateRoute<TParams>(route: IProcessedRoute, paramValues?: ParamValues<TParams>, includeQueryParams?: boolean): string;
|
|
6
|
+
static getQueryString<TParams>(route: IProcessedRoute, paramValues: ParamValues<TParams>): string;
|
|
7
|
+
static stringifyValue(value?: ValidParameterValue): string | null;
|
|
8
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
var RouteHelper = /** @class */ (function () {
|
|
2
|
+
function RouteHelper() {
|
|
3
|
+
}
|
|
4
|
+
/** Populates the route's path with the provided parameter values. */
|
|
5
|
+
RouteHelper.hydrateRoute = function (route, paramValues, includeQueryParams) {
|
|
6
|
+
var _a;
|
|
7
|
+
if (includeQueryParams === void 0) { includeQueryParams = true; }
|
|
8
|
+
paramValues !== null && paramValues !== void 0 ? paramValues : (paramValues = {});
|
|
9
|
+
var path = "";
|
|
10
|
+
var pending = "";
|
|
11
|
+
var index = 0;
|
|
12
|
+
for (var _i = 0, _b = route.segments; _i < _b.length; _i++) {
|
|
13
|
+
var segment = _b[_i];
|
|
14
|
+
if (segment.param) {
|
|
15
|
+
var rawValue = paramValues[segment.param.name];
|
|
16
|
+
var value = encodeURIComponent((_a = this.stringifyValue(rawValue)) !== null && _a !== void 0 ? _a : "");
|
|
17
|
+
pending += "/" + value;
|
|
18
|
+
if ((rawValue !== undefined && rawValue !== null) || index < route.requiredSegments) {
|
|
19
|
+
path += pending;
|
|
20
|
+
pending = "";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
path += "/" + segment.value;
|
|
25
|
+
}
|
|
26
|
+
index++;
|
|
27
|
+
}
|
|
28
|
+
var queryString = includeQueryParams ? this.getQueryString(route, paramValues) : "";
|
|
29
|
+
return path + queryString;
|
|
30
|
+
};
|
|
31
|
+
RouteHelper.getQueryString = function (route, paramValues) {
|
|
32
|
+
var _a;
|
|
33
|
+
var queryString = "";
|
|
34
|
+
for (var _i = 0, _b = route.queryParams; _i < _b.length; _i++) {
|
|
35
|
+
var queryParam = _b[_i];
|
|
36
|
+
var rawValue = paramValues[queryParam.name];
|
|
37
|
+
if (rawValue !== undefined && rawValue !== null) {
|
|
38
|
+
var value = encodeURIComponent((_a = this.stringifyValue(rawValue)) !== null && _a !== void 0 ? _a : "");
|
|
39
|
+
queryString += (queryString ? "&" : "?") + queryParam.name + "=" + value;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return queryString;
|
|
43
|
+
};
|
|
44
|
+
RouteHelper.stringifyValue = function (value) {
|
|
45
|
+
if (value instanceof Array) {
|
|
46
|
+
return value.join(",");
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
return value !== null && value !== undefined ? value.toString() : null;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
return RouteHelper;
|
|
53
|
+
}());
|
|
54
|
+
export { RouteHelper };
|
|
@@ -5,15 +5,23 @@ interface INamedRouteParameter extends IRouteParameter {
|
|
|
5
5
|
name: string;
|
|
6
6
|
}
|
|
7
7
|
export interface IProcessedRoute extends Routing.IRoute {
|
|
8
|
-
/**
|
|
9
|
-
|
|
8
|
+
/** Path with all parameters replaced by their default values. */
|
|
9
|
+
defaultPath: string;
|
|
10
10
|
/** Route params in order, excluding query parameters. */
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
routeParams: INamedRouteParameter[];
|
|
12
|
+
queryParams: INamedRouteParameter[];
|
|
13
|
+
/** The path split into segments, including parameter segments. */
|
|
14
|
+
segments: RouteSegment[];
|
|
15
|
+
/** The number of required segments in the path for this route to match. */
|
|
16
|
+
requiredSegments: number;
|
|
13
17
|
}
|
|
14
18
|
type ParamsObject = {
|
|
15
19
|
[index: string]: string | undefined;
|
|
16
20
|
};
|
|
21
|
+
type RouteSegment = {
|
|
22
|
+
value: string;
|
|
23
|
+
param?: INamedRouteParameter;
|
|
24
|
+
};
|
|
17
25
|
/**
|
|
18
26
|
* A route which has matched, with its parameter values populated from the path.
|
|
19
27
|
*/
|
|
@@ -28,8 +36,7 @@ export default class RouteProvider {
|
|
|
28
36
|
menuRoutes: Routing.IMenuRoute[];
|
|
29
37
|
pureRoutes?: Routing.IRoute[] | undefined;
|
|
30
38
|
notFoundComponent?: React.ComponentType | undefined;
|
|
31
|
-
private
|
|
32
|
-
private parameterisedRoutes;
|
|
39
|
+
private basePaths;
|
|
33
40
|
readonly allRoutes: IProcessedRoute[];
|
|
34
41
|
/**
|
|
35
42
|
* Creates a route provider which provides a list of flattened routes.
|
|
@@ -38,8 +45,10 @@ export default class RouteProvider {
|
|
|
38
45
|
* @param notFoundComponent Component to render when the url doesn't match any of the above routes.
|
|
39
46
|
*/
|
|
40
47
|
constructor(menuRoutes: Routing.IMenuRoute[], pureRoutes?: Routing.IRoute[] | undefined, notFoundComponent?: React.ComponentType | undefined);
|
|
41
|
-
/** Gets the path the component is bound to. If the component is bound to multiple paths, the first path is returned. */
|
|
48
|
+
/** Gets the raw route path the component is bound to. If the component is bound to multiple paths, the first path is returned. */
|
|
42
49
|
getPathForComponent(component: any): string | undefined;
|
|
50
|
+
/** Gets the route the component is bound to. If the component is bound to multiple routes, the first route is returned. */
|
|
51
|
+
getRouteForComponent(component: any): IProcessedRoute | undefined;
|
|
43
52
|
private flatten;
|
|
44
53
|
/**
|
|
45
54
|
* Create a copy of the route info, and process it.
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { __assign, __spreadArray } from "tslib";
|
|
2
|
+
import { RouteHelper } from "./RouteHelper";
|
|
3
|
+
var processedRouteSymbol = Symbol("processedRoute");
|
|
2
4
|
var RouteProvider = /** @class */ (function () {
|
|
3
5
|
/**
|
|
4
6
|
* Creates a route provider which provides a list of flattened routes.
|
|
@@ -10,91 +12,91 @@ var RouteProvider = /** @class */ (function () {
|
|
|
10
12
|
this.menuRoutes = menuRoutes;
|
|
11
13
|
this.pureRoutes = pureRoutes;
|
|
12
14
|
this.notFoundComponent = notFoundComponent;
|
|
13
|
-
this.
|
|
14
|
-
this.parameterisedRoutes = [];
|
|
15
|
+
this.basePaths = new Set();
|
|
15
16
|
this.allRoutes = [];
|
|
16
|
-
this.flatten(menuRoutes);
|
|
17
17
|
if (pureRoutes)
|
|
18
18
|
this.flatten(pureRoutes);
|
|
19
|
-
this.
|
|
20
|
-
this.parameterisedRoutes = this.allRoutes
|
|
21
|
-
.filter(function (c) { return c.params.length > 0; })
|
|
22
|
-
.sortBy(function (c) { return c.order; }, "desc");
|
|
19
|
+
this.flatten(menuRoutes);
|
|
23
20
|
}
|
|
24
|
-
/** Gets the path the component is bound to. If the component is bound to multiple paths, the first path is returned. */
|
|
21
|
+
/** Gets the raw route path the component is bound to. If the component is bound to multiple paths, the first path is returned. */
|
|
25
22
|
RouteProvider.prototype.getPathForComponent = function (component) {
|
|
26
23
|
var _a;
|
|
27
|
-
return (_a = this.
|
|
24
|
+
return (_a = this.getRouteForComponent(component)) === null || _a === void 0 ? void 0 : _a.defaultPath;
|
|
25
|
+
};
|
|
26
|
+
/** Gets the route the component is bound to. If the component is bound to multiple routes, the first route is returned. */
|
|
27
|
+
RouteProvider.prototype.getRouteForComponent = function (component) {
|
|
28
|
+
return this.allRoutes.find(function (c) { return c.component === component; });
|
|
28
29
|
};
|
|
29
30
|
/** @internal */
|
|
30
|
-
RouteProvider.
|
|
31
|
-
|
|
31
|
+
RouteProvider.getProcessedRoute = function (route) {
|
|
32
|
+
var _a;
|
|
33
|
+
// @ts-ignore
|
|
34
|
+
var processed = route[processedRouteSymbol];
|
|
35
|
+
if (!processed) {
|
|
36
|
+
throw new Error("Route has not been processed: ".concat((_a = route.basePath) !== null && _a !== void 0 ? _a : route.path));
|
|
37
|
+
}
|
|
38
|
+
return processed;
|
|
32
39
|
};
|
|
33
40
|
/** @internal */
|
|
34
|
-
RouteProvider.getRouteForPath = function (
|
|
41
|
+
RouteProvider.prototype.getRouteForPath = function (path) {
|
|
42
|
+
var _a;
|
|
35
43
|
var queryIndex = path.indexOf("?");
|
|
36
44
|
if (queryIndex >= 0) {
|
|
37
45
|
path = path.substring(0, queryIndex);
|
|
38
46
|
}
|
|
39
|
-
var
|
|
40
|
-
var
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
var paramString = path.substring(match.path.length);
|
|
56
|
-
// Special case for root path which has its leading "/" removed by the navigation helper.
|
|
57
|
-
if (match.path === "/") {
|
|
58
|
-
paramString = "/" + paramString;
|
|
59
|
-
}
|
|
60
|
-
var parts = paramString.split("/").slice(1);
|
|
61
|
-
var partCount = parts.length;
|
|
62
|
-
// Allow extra "/"
|
|
63
|
-
if (partCount > 0 && parts[partCount - 1] === "") {
|
|
64
|
-
partCount -= 1;
|
|
65
|
-
}
|
|
66
|
-
if (match.params.length >= partCount) {
|
|
67
|
-
var paramValues = {};
|
|
68
|
-
var isValid = true;
|
|
69
|
-
for (var i = 0; i < match.params.length; i++) {
|
|
70
|
-
var param = match.params[i];
|
|
71
|
-
var value = parts[i];
|
|
72
|
-
paramValues[param.name] = value;
|
|
73
|
-
if (param.required && !value) {
|
|
74
|
-
isValid = false;
|
|
75
|
-
break;
|
|
47
|
+
var providedSegments = path.split("/").slice(1);
|
|
48
|
+
var currentRoutes = this.allRoutes.filter(function (r) { return providedSegments.length >= r.requiredSegments; });
|
|
49
|
+
var params = [];
|
|
50
|
+
for (var i = 0; i < providedSegments.length; i++) {
|
|
51
|
+
var segmentValue = providedSegments[i];
|
|
52
|
+
var matchedRoutes = [];
|
|
53
|
+
for (var _i = 0, currentRoutes_1 = currentRoutes; _i < currentRoutes_1.length; _i++) {
|
|
54
|
+
var route = currentRoutes_1[_i];
|
|
55
|
+
var routeSegment = route.segments.length > i ? route.segments[i] : undefined;
|
|
56
|
+
if (segmentValue.toLowerCase() === ((_a = routeSegment === null || routeSegment === void 0 ? void 0 : routeSegment.value) !== null && _a !== void 0 ? _a : "")) {
|
|
57
|
+
matchedRoutes.push(route);
|
|
58
|
+
}
|
|
59
|
+
else if (routeSegment && routeSegment.param) {
|
|
60
|
+
params.push({ param: routeSegment.param, value: segmentValue, index: i });
|
|
61
|
+
if (!routeSegment.param.required || segmentValue) {
|
|
62
|
+
matchedRoutes.push(route);
|
|
76
63
|
}
|
|
77
64
|
}
|
|
78
|
-
|
|
79
|
-
|
|
65
|
+
}
|
|
66
|
+
currentRoutes = matchedRoutes;
|
|
67
|
+
}
|
|
68
|
+
if (currentRoutes.length > 0) {
|
|
69
|
+
var route = currentRoutes[0];
|
|
70
|
+
var paramValues = {};
|
|
71
|
+
var _loop_1 = function (i) {
|
|
72
|
+
var segment = route.segments[i];
|
|
73
|
+
if (segment.param) {
|
|
74
|
+
var paramInfo = params.find(function (p) { return p.param == segment.param && p.index === i; });
|
|
75
|
+
paramValues[segment.param.name] = paramInfo === null || paramInfo === void 0 ? void 0 : paramInfo.value;
|
|
80
76
|
}
|
|
77
|
+
};
|
|
78
|
+
for (var i = 0; i < route.segments.length; i++) {
|
|
79
|
+
_loop_1(i);
|
|
81
80
|
}
|
|
81
|
+
return { route: route, path: path, params: paramValues };
|
|
82
82
|
}
|
|
83
83
|
return null;
|
|
84
84
|
};
|
|
85
85
|
RouteProvider.prototype.flatten = function (routes, parent) {
|
|
86
|
-
var _a, _b;
|
|
86
|
+
var _a, _b, _c;
|
|
87
87
|
for (var _i = 0, routes_1 = routes; _i < routes_1.length; _i++) {
|
|
88
88
|
var route = routes_1[_i];
|
|
89
|
-
var
|
|
89
|
+
var baseRoute = (_a = route.baseRoute) !== null && _a !== void 0 ? _a : route;
|
|
90
|
+
var hasComponent = baseRoute.path !== undefined && baseRoute.component;
|
|
90
91
|
if (hasComponent) {
|
|
91
92
|
if (parent && !route.breadCrumbParent) {
|
|
93
|
+
baseRoute.breadCrumbParent = parent;
|
|
92
94
|
route.breadCrumbParent = parent;
|
|
93
95
|
}
|
|
94
|
-
this.processRoute(
|
|
96
|
+
this.processRoute(baseRoute);
|
|
95
97
|
}
|
|
96
98
|
var menuRoute = route;
|
|
97
|
-
var children = __spreadArray(__spreadArray([], ((
|
|
99
|
+
var children = __spreadArray(__spreadArray([], ((_b = route.routeChildren) !== null && _b !== void 0 ? _b : []), true), ((_c = menuRoute.children) !== null && _c !== void 0 ? _c : []), true);
|
|
98
100
|
this.flatten(children, (hasComponent && menuRoute.showInBreadCrumb !== false) ? menuRoute : undefined);
|
|
99
101
|
}
|
|
100
102
|
};
|
|
@@ -104,25 +106,73 @@ var RouteProvider = /** @class */ (function () {
|
|
|
104
106
|
*/
|
|
105
107
|
RouteProvider.prototype.processRoute = function (route) {
|
|
106
108
|
var _a;
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
if (processed.path.length > 1 && processed.path.endsWith("/")) {
|
|
111
|
-
processed.path = processed.path.substring(0, processed.path.length - 1);
|
|
109
|
+
// @ts-ignore
|
|
110
|
+
if (route[processedRouteSymbol]) {
|
|
111
|
+
return;
|
|
112
112
|
}
|
|
113
|
-
|
|
114
|
-
|
|
113
|
+
var processed = __assign(__assign({}, route), { defaultPath: ((_a = route.basePath) !== null && _a !== void 0 ? _a : route.path), routeParams: [], queryParams: [], segments: [], requiredSegments: 0 });
|
|
114
|
+
// @ts-ignore
|
|
115
|
+
route[processedRouteSymbol] = processed;
|
|
116
|
+
var normalizedPath = processed.defaultPath.toLowerCase();
|
|
117
|
+
var fullPath = normalizedPath;
|
|
118
|
+
var hasParamIdentifier = false;
|
|
119
|
+
if (normalizedPath.endsWith("/")) {
|
|
120
|
+
normalizedPath = normalizedPath.substring(0, normalizedPath.length - 1);
|
|
115
121
|
}
|
|
116
122
|
var viewBaseComponent = route.component;
|
|
117
123
|
if (viewBaseComponent.params) {
|
|
118
124
|
for (var param in viewBaseComponent.params) {
|
|
119
125
|
var routeParam = viewBaseComponent.params[param];
|
|
120
126
|
if (!routeParam.isQuery) {
|
|
121
|
-
processed.
|
|
127
|
+
processed.routeParams.push(__assign(__assign({}, routeParam), { name: param }));
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
processed.queryParams.push(__assign(__assign({}, routeParam), { name: param }));
|
|
122
131
|
}
|
|
123
132
|
}
|
|
124
133
|
}
|
|
125
|
-
|
|
134
|
+
// Split the path into segments, and identify which segments are parameters.
|
|
135
|
+
var segmentValues = normalizedPath.split("/").slice(1);
|
|
136
|
+
var params = __spreadArray([], processed.routeParams, true);
|
|
137
|
+
var _loop_2 = function (segmentValue) {
|
|
138
|
+
var segment = { value: segmentValue };
|
|
139
|
+
processed.segments.push(segment);
|
|
140
|
+
if (segmentValue.startsWith(":")) {
|
|
141
|
+
hasParamIdentifier = true;
|
|
142
|
+
var paramName_1 = segmentValue.substring(1);
|
|
143
|
+
segment.param = processed.routeParams.find(function (p) { return p.name.toLowerCase() === paramName_1; });
|
|
144
|
+
if (segment.param) {
|
|
145
|
+
params.remove(segment.param);
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
throw Error("Route parameter \"".concat(paramName_1, "\" in path \"").concat(processed.defaultPath, "\" does not have a corresponding view parameter definition."));
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (!segment.param || segment.param.required) {
|
|
152
|
+
processed.requiredSegments = processed.segments.length;
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
for (var _i = 0, segmentValues_1 = segmentValues; _i < segmentValues_1.length; _i++) {
|
|
156
|
+
var segmentValue = segmentValues_1[_i];
|
|
157
|
+
_loop_2(segmentValue);
|
|
158
|
+
}
|
|
159
|
+
// Params that aren't in the path are added as segments at the end of the path.
|
|
160
|
+
for (var _b = 0, params_1 = params; _b < params_1.length; _b++) {
|
|
161
|
+
var param = params_1[_b];
|
|
162
|
+
var segmentValue = ":".concat(param.name);
|
|
163
|
+
processed.segments.push({ value: segmentValue, param: param });
|
|
164
|
+
fullPath += "/".concat(segmentValue);
|
|
165
|
+
if (param.required) {
|
|
166
|
+
processed.requiredSegments = processed.segments.length;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
if (hasParamIdentifier) {
|
|
170
|
+
processed.defaultPath = RouteHelper.hydrateRoute(processed, {});
|
|
171
|
+
}
|
|
172
|
+
if (!this.basePaths.has(fullPath)) {
|
|
173
|
+
this.basePaths.add(fullPath);
|
|
174
|
+
this.allRoutes.push(processed);
|
|
175
|
+
}
|
|
126
176
|
};
|
|
127
177
|
return RouteProvider;
|
|
128
178
|
}());
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { IRouteParameter } from './IRouteParameter';
|
|
2
|
-
import {
|
|
1
|
+
import { IRouteParameter, ValidParameterValue } from './IRouteParameter';
|
|
2
|
+
import { IViewParameterList } from './ViewParameterList';
|
|
3
3
|
import { Model } from '@singularsystems/neo-core';
|
|
4
4
|
export interface IViewParameter {
|
|
5
5
|
/**
|
|
6
6
|
* Gets or sets the current parameter value.
|
|
7
7
|
*/
|
|
8
|
-
value:
|
|
8
|
+
value: ValidParameterValue;
|
|
9
9
|
/**
|
|
10
10
|
* Clears the value, replacing the url instead of adding to the history.
|
|
11
11
|
* This prevents the back button returning the params to the current state.
|
|
@@ -42,7 +42,7 @@ export interface IViewParameter {
|
|
|
42
42
|
/**
|
|
43
43
|
* Allows this view parameter to automatically update when the value returned in the provided callback changes.
|
|
44
44
|
*/
|
|
45
|
-
bindTo(callback: () =>
|
|
45
|
+
bindTo(callback: () => ValidParameterValue): void;
|
|
46
46
|
}
|
|
47
47
|
export declare class ViewParameter implements IViewParameter {
|
|
48
48
|
private parent;
|
|
@@ -52,10 +52,10 @@ export declare class ViewParameter implements IViewParameter {
|
|
|
52
52
|
private pendingValue;
|
|
53
53
|
private _value;
|
|
54
54
|
prefixes: IViewParameterPrefix[];
|
|
55
|
-
constructor(parent:
|
|
56
|
-
bindTo(propertyOrCallback: Model.IPropertyInstance | (() =>
|
|
57
|
-
get value():
|
|
58
|
-
set value(value:
|
|
55
|
+
constructor(parent: IViewParameterList, name: string, routeParameter: IRouteParameter);
|
|
56
|
+
bindTo(propertyOrCallback: Model.IPropertyInstance | (() => ValidParameterValue)): void;
|
|
57
|
+
get value(): ValidParameterValue;
|
|
58
|
+
set value(value: ValidParameterValue);
|
|
59
59
|
reset(): void;
|
|
60
60
|
_description: string;
|
|
61
61
|
get description(): string;
|
|
@@ -66,17 +66,12 @@ export declare class ViewParameter implements IViewParameter {
|
|
|
66
66
|
asStringList(): string[];
|
|
67
67
|
/** Updates the current value, and returns true if the value changed. */
|
|
68
68
|
update(value: string | null): boolean;
|
|
69
|
-
getParamString(state: {
|
|
70
|
-
hasQuery: boolean;
|
|
71
|
-
}): string;
|
|
72
|
-
get latestValue(): string | null;
|
|
73
|
-
private getStringValue;
|
|
74
69
|
}
|
|
75
70
|
interface IViewParameterPrefix {
|
|
76
71
|
/** Label to show on breadcrumb. */
|
|
77
72
|
label: string;
|
|
78
73
|
/** Value to use in the breadcrumb link. Clicking on the link will set the view parameter to this value. */
|
|
79
|
-
value?:
|
|
74
|
+
value?: ValidParameterValue;
|
|
80
75
|
/** Custom link to use in the breadcrumb. */
|
|
81
76
|
link?: string;
|
|
82
77
|
/** Click event for the breadcrumb. */
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { __decorate, __metadata } from "tslib";
|
|
2
2
|
import { makeObservable, observable } from 'mobx';
|
|
3
|
+
import { RouteHelper } from './RouteHelper';
|
|
3
4
|
var ViewParameter = /** @class */ (function () {
|
|
4
5
|
function ViewParameter(parent, name, routeParameter) {
|
|
5
6
|
this.parent = parent;
|
|
@@ -15,22 +16,22 @@ var ViewParameter = /** @class */ (function () {
|
|
|
15
16
|
ViewParameter.prototype.bindTo = function (propertyOrCallback) {
|
|
16
17
|
var _this = this;
|
|
17
18
|
if (propertyOrCallback.propertyInfo) {
|
|
18
|
-
this.parent.
|
|
19
|
+
this.parent._view.viewModel.registerReaction(function () { return propertyOrCallback.value; }, function (val) { return _this.value = val; });
|
|
19
20
|
}
|
|
20
21
|
else if (propertyOrCallback instanceof Function) {
|
|
21
|
-
this.parent.
|
|
22
|
+
this.parent._view.viewModel.registerReaction(propertyOrCallback, function (val) { return _this.value = val; });
|
|
22
23
|
}
|
|
23
24
|
};
|
|
24
25
|
Object.defineProperty(ViewParameter.prototype, "value", {
|
|
25
26
|
get: function () {
|
|
26
|
-
return this._value;
|
|
27
|
+
return this.hasPendingValue ? this.pendingValue : this._value;
|
|
27
28
|
},
|
|
28
29
|
set: function (value) {
|
|
29
|
-
var stringValue =
|
|
30
|
+
var stringValue = RouteHelper.stringifyValue(value);
|
|
30
31
|
if (stringValue !== this._value) {
|
|
31
32
|
this.hasPendingValue = true;
|
|
32
33
|
this.pendingValue = stringValue;
|
|
33
|
-
this.parent.setUrl(this);
|
|
34
|
+
this.parent.setUrl(this, value);
|
|
34
35
|
}
|
|
35
36
|
},
|
|
36
37
|
enumerable: false,
|
|
@@ -40,7 +41,7 @@ var ViewParameter = /** @class */ (function () {
|
|
|
40
41
|
if (this._value) {
|
|
41
42
|
this.hasPendingValue = true;
|
|
42
43
|
this.pendingValue = null;
|
|
43
|
-
this.parent.setUrl(this, true);
|
|
44
|
+
this.parent.setUrl(this, null, true);
|
|
44
45
|
}
|
|
45
46
|
};
|
|
46
47
|
Object.defineProperty(ViewParameter.prototype, "description", {
|
|
@@ -94,36 +95,6 @@ var ViewParameter = /** @class */ (function () {
|
|
|
94
95
|
}
|
|
95
96
|
return false;
|
|
96
97
|
};
|
|
97
|
-
ViewParameter.prototype.getParamString = function (state) {
|
|
98
|
-
var value = this.latestValue;
|
|
99
|
-
if (value) {
|
|
100
|
-
value = encodeURIComponent(value);
|
|
101
|
-
if (this.routeParameter.isQuery) {
|
|
102
|
-
var hasQuery = state.hasQuery;
|
|
103
|
-
state.hasQuery = true;
|
|
104
|
-
return (!hasQuery ? "?" : "&") + this.name + "=" + value;
|
|
105
|
-
}
|
|
106
|
-
else {
|
|
107
|
-
return "/" + value;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
return this.routeParameter.isQuery ? "" : "/";
|
|
111
|
-
};
|
|
112
|
-
Object.defineProperty(ViewParameter.prototype, "latestValue", {
|
|
113
|
-
get: function () {
|
|
114
|
-
return this.hasPendingValue ? this.pendingValue : this._value;
|
|
115
|
-
},
|
|
116
|
-
enumerable: false,
|
|
117
|
-
configurable: true
|
|
118
|
-
});
|
|
119
|
-
ViewParameter.prototype.getStringValue = function (value) {
|
|
120
|
-
if (value instanceof Array) {
|
|
121
|
-
return value.join(",");
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
return value ? value.toString() : null;
|
|
125
|
-
}
|
|
126
|
-
};
|
|
127
98
|
__decorate([
|
|
128
99
|
observable.ref,
|
|
129
100
|
__metadata("design:type", String)
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { ViewParameter, IViewParameter } from './ViewParameter';
|
|
2
|
-
import { RouteParameterObject } from './IRouteParameter';
|
|
2
|
+
import { RouteParameterObject, ParamValues, ValidParameterValue } from './IRouteParameter';
|
|
3
3
|
import { BreadCrumbItem } from './BreadCrumbItem';
|
|
4
4
|
import { IViewBase } from '../Views/ViewBase';
|
|
5
|
-
import {
|
|
5
|
+
import { IProcessedRoute } from "./RouteProvider";
|
|
6
|
+
import { INavigationHelper } from './NavigationHelper';
|
|
6
7
|
export type TransformParamsType<T> = {
|
|
7
8
|
[P in keyof T]: IViewParameter;
|
|
8
9
|
};
|
|
@@ -16,39 +17,24 @@ export interface IViewParameterList {
|
|
|
16
17
|
/**
|
|
17
18
|
* Returns the breadcrumb items for all url parameters which have a value.
|
|
18
19
|
*/
|
|
19
|
-
getBreadCrumbList(
|
|
20
|
+
getBreadCrumbList(): BreadCrumbItem[];
|
|
20
21
|
}
|
|
21
22
|
export interface IViewParameterListOfT<TParams extends RouteParameterObject<TParams>> extends IViewParameterList {
|
|
22
23
|
/**
|
|
23
24
|
* Set the view params for each of the provided values. Only 1 navigation event will occur.
|
|
24
25
|
* @param values New values.
|
|
25
26
|
*/
|
|
26
|
-
setValues(values:
|
|
27
|
-
[P in keyof TParams]?: number | string | string[] | null;
|
|
28
|
-
}, options?: ISetValuesOptions | boolean): void;
|
|
27
|
+
setValues(values: ParamValues<TParams>, options?: ISetValuesOptions | boolean): void;
|
|
29
28
|
}
|
|
30
|
-
export
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
export declare class ViewParameterList<TParams extends RouteParameterObject<TParams>> implements IViewParameterListInternal, IViewParameterListOfT<TParams> {
|
|
35
|
-
readonly view?: IViewBase | undefined;
|
|
29
|
+
export declare class ViewParameterList<TParams extends RouteParameterObject<TParams>> implements IViewParameterListOfT<TParams> {
|
|
30
|
+
private _processedRoute;
|
|
31
|
+
private _navigationHelper;
|
|
32
|
+
readonly _view?: IViewBase | undefined;
|
|
36
33
|
readonly params: ViewParameter[];
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
private
|
|
42
|
-
setValues(values: {
|
|
43
|
-
[P in keyof TParams]?: number | string | string[] | null;
|
|
44
|
-
}, options?: ISetValuesOptions | boolean): void;
|
|
45
|
-
setUrl(viewParameter: ViewParameter | null, replace?: boolean): void;
|
|
46
|
-
getUrl(viewParameter: ViewParameter): string | undefined;
|
|
47
|
-
/**
|
|
48
|
-
* Gets a url for an object with view params specified.
|
|
49
|
-
* @param basePath Base path without parameters
|
|
50
|
-
* @param values Object of param names and values.
|
|
51
|
-
*/
|
|
52
|
-
static getPathForValues<TParams extends RouteParameterObject<TParams>>(basePath: string, params: TParams, values: ParamValues<TParams>): string;
|
|
34
|
+
constructor(_processedRoute: IProcessedRoute, _navigationHelper: INavigationHelper, _view?: IViewBase | undefined);
|
|
35
|
+
getBreadCrumbList(): BreadCrumbItem[];
|
|
36
|
+
setValues(values: ParamValues<TParams>, options?: ISetValuesOptions | boolean): void;
|
|
37
|
+
setUrl(viewParameter: ViewParameter | null, newValue: ValidParameterValue, replace?: boolean): void;
|
|
38
|
+
private navigate;
|
|
53
39
|
}
|
|
54
40
|
export {};
|
|
@@ -1,123 +1,112 @@
|
|
|
1
|
+
import { __spreadArray } from "tslib";
|
|
1
2
|
import { ViewParameter } from './ViewParameter';
|
|
2
3
|
import { BreadCrumbSelectMode } from './IRouteParameter';
|
|
3
4
|
import { BreadCrumbItem } from './BreadCrumbItem';
|
|
4
|
-
import {
|
|
5
|
-
import { NeoReactTypes } from '../Modules/Types';
|
|
5
|
+
import { RouteHelper } from './RouteHelper';
|
|
6
6
|
var ViewParameterList = /** @class */ (function () {
|
|
7
|
-
function ViewParameterList(
|
|
8
|
-
this.
|
|
7
|
+
function ViewParameterList(_processedRoute, _navigationHelper, _view) {
|
|
8
|
+
this._processedRoute = _processedRoute;
|
|
9
|
+
this._navigationHelper = _navigationHelper;
|
|
10
|
+
this._view = _view;
|
|
9
11
|
this.params = [];
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
this[param] = viewParam;
|
|
17
|
-
this.params.push(viewParam);
|
|
18
|
-
}
|
|
12
|
+
for (var _i = 0, _a = __spreadArray(__spreadArray([], _processedRoute.routeParams, true), _processedRoute.queryParams, true); _i < _a.length; _i++) {
|
|
13
|
+
var param = _a[_i];
|
|
14
|
+
var viewParam = new ViewParameter(this, param.name, param);
|
|
15
|
+
//@ts-ignore
|
|
16
|
+
this[param.name] = viewParam;
|
|
17
|
+
this.params.push(viewParam);
|
|
19
18
|
}
|
|
20
19
|
}
|
|
21
|
-
ViewParameterList.prototype.getBreadCrumbList = function (
|
|
20
|
+
ViewParameterList.prototype.getBreadCrumbList = function () {
|
|
22
21
|
var _a;
|
|
23
|
-
var basePath = Misc.Globals.appService.get(NeoReactTypes.Routing.NavigationHelper).getCurrentViewPath();
|
|
24
22
|
var breadCrumbs = [];
|
|
25
|
-
var
|
|
26
|
-
var queryPath = this.getQueryString(state);
|
|
27
|
-
var paramPath = basePath;
|
|
28
|
-
var selectablePath = basePath;
|
|
23
|
+
var values = {};
|
|
29
24
|
for (var _i = 0, _b = this.params; _i < _b.length; _i++) {
|
|
30
|
-
var
|
|
25
|
+
var param = _b[_i];
|
|
26
|
+
if (param.routeParameter.isQuery) {
|
|
27
|
+
values[param.name] = param.value;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
var queryPath = RouteHelper.getQueryString(this._processedRoute, values);
|
|
31
|
+
var paramPath;
|
|
32
|
+
var selectablePath;
|
|
33
|
+
for (var _c = 0, _d = this.params; _c < _d.length; _c++) {
|
|
34
|
+
var viewParam = _d[_c];
|
|
31
35
|
if (!viewParam.routeParameter.isQuery) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
breadcrumbItem.link = prefix.link;
|
|
41
|
-
}
|
|
42
|
-
else if (prefix.value) {
|
|
43
|
-
breadcrumbItem.link = paramPath + "/" + prefix.value;
|
|
44
|
-
}
|
|
45
|
-
breadCrumbs.push(breadcrumbItem);
|
|
36
|
+
for (var _e = 0, _f = viewParam.prefixes; _e < _f.length; _e++) {
|
|
37
|
+
var prefix = _f[_e];
|
|
38
|
+
var breadcrumbItem = new BreadCrumbItem(prefix.label);
|
|
39
|
+
if (prefix.onClick) {
|
|
40
|
+
breadcrumbItem.onClick = prefix.onClick;
|
|
41
|
+
}
|
|
42
|
+
else if (prefix.link) {
|
|
43
|
+
breadcrumbItem.link = prefix.link;
|
|
46
44
|
}
|
|
45
|
+
else if (prefix.value) {
|
|
46
|
+
values[viewParam.name] = prefix.value;
|
|
47
|
+
breadcrumbItem.link = RouteHelper.hydrateRoute(this._processedRoute, values, false);
|
|
48
|
+
}
|
|
49
|
+
breadCrumbs.push(breadcrumbItem);
|
|
47
50
|
}
|
|
48
|
-
|
|
51
|
+
values[viewParam.name] = viewParam.value;
|
|
52
|
+
paramPath = RouteHelper.hydrateRoute(this._processedRoute, values, false);
|
|
49
53
|
if (((_a = viewParam.routeParameter.selection) !== null && _a !== void 0 ? _a : BreadCrumbSelectMode.Default) === BreadCrumbSelectMode.Default) {
|
|
50
54
|
selectablePath = paramPath;
|
|
51
55
|
}
|
|
52
|
-
if (viewParam.description ||
|
|
53
|
-
breadCrumbs.push(new BreadCrumbItem(viewParam.description, (
|
|
56
|
+
if (viewParam.description || viewParam.value !== null) {
|
|
57
|
+
breadCrumbs.push(new BreadCrumbItem(viewParam.description, (viewParam.routeParameter.selection === BreadCrumbSelectMode.None) ? "" : (selectablePath + queryPath)));
|
|
54
58
|
}
|
|
55
59
|
}
|
|
56
|
-
if (upTo && upTo === viewParam) {
|
|
57
|
-
break;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
if (breadCrumbs.length === 0 && state.hasQuery) {
|
|
61
|
-
breadCrumbs.push(new BreadCrumbItem("", basePath + queryPath));
|
|
62
60
|
}
|
|
63
61
|
return breadCrumbs;
|
|
64
62
|
};
|
|
65
|
-
ViewParameterList.prototype.getQueryString = function (state) {
|
|
66
|
-
var queryPath = "";
|
|
67
|
-
for (var _i = 0, _a = this.params; _i < _a.length; _i++) {
|
|
68
|
-
var viewParam = _a[_i];
|
|
69
|
-
if (viewParam.routeParameter.isQuery) {
|
|
70
|
-
queryPath += viewParam.getParamString(state);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
return queryPath;
|
|
74
|
-
};
|
|
75
63
|
ViewParameterList.prototype.setValues = function (values, options) {
|
|
76
|
-
var _a;
|
|
77
|
-
this.suppressNavigation = true;
|
|
78
|
-
this.hasSuppressedNavigation = false;
|
|
79
64
|
options !== null && options !== void 0 ? options : (options = {});
|
|
80
65
|
if (typeof options === "boolean") {
|
|
81
66
|
options = { force: true }; // parameter used to be named 'force'- backwards compatibility.
|
|
82
67
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
68
|
+
var hasChange = false;
|
|
69
|
+
var newValues = {};
|
|
70
|
+
for (var _i = 0, _a = this.params; _i < _a.length; _i++) {
|
|
71
|
+
var param = _a[_i];
|
|
72
|
+
var hasNewValue = values[param.name] !== undefined;
|
|
73
|
+
var newValue = RouteHelper.stringifyValue(values[param.name]);
|
|
74
|
+
if (hasNewValue && newValue != param.value) {
|
|
75
|
+
hasChange = true;
|
|
76
|
+
}
|
|
77
|
+
newValues[param.name] = hasNewValue ? newValue : param.value;
|
|
86
78
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
this.setUrl(this.params[this.params.length - 1], options.replace);
|
|
79
|
+
if (hasChange || options.force) {
|
|
80
|
+
this.navigate(newValues, options.replace);
|
|
90
81
|
}
|
|
91
82
|
};
|
|
92
|
-
ViewParameterList.prototype.setUrl = function (viewParameter, replace) {
|
|
83
|
+
ViewParameterList.prototype.setUrl = function (viewParameter, newValue, replace) {
|
|
93
84
|
if (replace === void 0) { replace = false; }
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
85
|
+
var canAdd = true;
|
|
86
|
+
var newValues = {};
|
|
87
|
+
for (var _i = 0, _a = this.params; _i < _a.length; _i++) {
|
|
88
|
+
var param = _a[_i];
|
|
89
|
+
if (canAdd || param.routeParameter.isQuery) {
|
|
90
|
+
if (param === viewParameter) {
|
|
91
|
+
newValues[param.name] = newValue;
|
|
92
|
+
canAdd = false;
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
newValues[param.name] = param.value;
|
|
104
96
|
}
|
|
105
97
|
}
|
|
106
|
-
navigationHelper.navigateInternal(navigationHelper.getCurrentViewPath(), replace);
|
|
107
98
|
}
|
|
99
|
+
this.navigate(newValues, replace);
|
|
108
100
|
};
|
|
109
|
-
ViewParameterList.prototype.
|
|
110
|
-
var
|
|
111
|
-
|
|
112
|
-
return allItems[allItems.length - 1].link;
|
|
113
|
-
}
|
|
114
|
-
return undefined;
|
|
101
|
+
ViewParameterList.prototype.navigate = function (values, replace) {
|
|
102
|
+
var path = RouteHelper.hydrateRoute(this._processedRoute, values);
|
|
103
|
+
this._navigationHelper.navigateInternal(path, replace);
|
|
115
104
|
};
|
|
116
105
|
/**
|
|
117
106
|
* @internal
|
|
118
107
|
* Updates the parameter values from the values in the url. Returns true if any of the values have changed.
|
|
119
108
|
*/
|
|
120
|
-
ViewParameterList.prototype.update = function (match) {
|
|
109
|
+
ViewParameterList.prototype.update = function (match, queryString) {
|
|
121
110
|
var hasChanged = false;
|
|
122
111
|
//Get url params
|
|
123
112
|
for (var param in match.params) {
|
|
@@ -130,7 +119,7 @@ var ViewParameterList = /** @class */ (function () {
|
|
|
130
119
|
}
|
|
131
120
|
}
|
|
132
121
|
//Get query params
|
|
133
|
-
var queryParams = new URLSearchParams(
|
|
122
|
+
var queryParams = new URLSearchParams(queryString);
|
|
134
123
|
for (var _i = 0, _a = this.params; _i < _a.length; _i++) {
|
|
135
124
|
var viewParam = _a[_i];
|
|
136
125
|
if (viewParam.routeParameter.isQuery) {
|
|
@@ -140,39 +129,6 @@ var ViewParameterList = /** @class */ (function () {
|
|
|
140
129
|
}
|
|
141
130
|
return hasChanged;
|
|
142
131
|
};
|
|
143
|
-
/**
|
|
144
|
-
* Gets a url for an object with view params specified.
|
|
145
|
-
* @param basePath Base path without parameters
|
|
146
|
-
* @param values Object of param names and values.
|
|
147
|
-
*/
|
|
148
|
-
ViewParameterList.getPathForValues = function (basePath, params, values) {
|
|
149
|
-
// TODO: This needs a rework.
|
|
150
|
-
var viewParameterList = new ViewParameterList(params);
|
|
151
|
-
for (var name_1 in values) {
|
|
152
|
-
//@ts-ignore
|
|
153
|
-
var viewParam = viewParameterList[name_1];
|
|
154
|
-
if (viewParam) {
|
|
155
|
-
var value = values[name_1];
|
|
156
|
-
if (value === undefined)
|
|
157
|
-
value = null;
|
|
158
|
-
if (typeof value === "number") {
|
|
159
|
-
value = value.toString();
|
|
160
|
-
}
|
|
161
|
-
viewParam.update(value);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
var state = { hasQuery: false };
|
|
165
|
-
var paramPath = basePath;
|
|
166
|
-
for (var _i = 0, _a = viewParameterList.params.filter(function (c) { return !c.routeParameter.isQuery; }); _i < _a.length; _i++) {
|
|
167
|
-
var viewParam = _a[_i];
|
|
168
|
-
paramPath += viewParam.getParamString(state);
|
|
169
|
-
}
|
|
170
|
-
// trim trailing slashes
|
|
171
|
-
while (paramPath.endsWith("/")) {
|
|
172
|
-
paramPath = paramPath.substring(0, paramPath.length - 1);
|
|
173
|
-
}
|
|
174
|
-
return paramPath + viewParameterList.getQueryString(state);
|
|
175
|
-
};
|
|
176
132
|
return ViewParameterList;
|
|
177
133
|
}());
|
|
178
134
|
export { ViewParameterList };
|
package/dist/Views/ViewBase.js
CHANGED
|
@@ -68,8 +68,7 @@ var ViewBase = /** @class */ (function (_super) {
|
|
|
68
68
|
return this.createViewState(viewModel);
|
|
69
69
|
};
|
|
70
70
|
ViewBase.prototype.createViewState = function (viewModel) {
|
|
71
|
-
var
|
|
72
|
-
var paramsList = new ViewParameterList(params, this);
|
|
71
|
+
var paramsList = new ViewParameterList(this.routingState.currentRoute.route, this.navigation, this);
|
|
73
72
|
var viewModelInstance = ViewModelBase.create(viewModel);
|
|
74
73
|
return new ViewState(paramsList, viewModelInstance);
|
|
75
74
|
};
|
|
@@ -79,7 +78,7 @@ var ViewBase = /** @class */ (function (_super) {
|
|
|
79
78
|
return __generator(this, function (_a) {
|
|
80
79
|
switch (_a.label) {
|
|
81
80
|
case 0:
|
|
82
|
-
paramsUpdated = this.routingState.currentRoute ? (this.viewState.viewParams).update(this.routingState.currentRoute) : false;
|
|
81
|
+
paramsUpdated = this.routingState.currentRoute ? (this.viewState.viewParams).update(this.routingState.currentRoute, location.search) : false;
|
|
83
82
|
if (!!this.viewState.hasSetup) return [3 /*break*/, 2];
|
|
84
83
|
this.viewState.hasSetup = true;
|
|
85
84
|
return [4 /*yield*/, this.initialise()];
|
|
@@ -108,7 +107,7 @@ var ViewBase = /** @class */ (function (_super) {
|
|
|
108
107
|
return __generator(this, function (_a) {
|
|
109
108
|
switch (_a.label) {
|
|
110
109
|
case 0:
|
|
111
|
-
if (!(this.viewState.viewParams).update(match)) return [3 /*break*/, 2];
|
|
110
|
+
if (!(this.viewState.viewParams).update(match, location.search)) return [3 /*break*/, 2];
|
|
112
111
|
return [4 /*yield*/, this.viewParamsUpdated()];
|
|
113
112
|
case 1:
|
|
114
113
|
_a.sent();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@singularsystems/neo-react",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.1",
|
|
4
4
|
"description": "React application logic and components for the Neo client library",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"typescript": "5.9.3"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@singularsystems/neo-core": "1.
|
|
30
|
+
"@singularsystems/neo-core": "1.6.1",
|
|
31
31
|
"@types/react-color": "3.0.13",
|
|
32
32
|
"axios": "1.13.5",
|
|
33
33
|
"inversify": "6.0.2",
|
package/styles/Forms.scss
CHANGED
|
@@ -65,7 +65,7 @@ div.neo-form-group-floating {
|
|
|
65
65
|
transform: scale(1);
|
|
66
66
|
}
|
|
67
67
|
label.neo-floating-label {
|
|
68
|
-
color:
|
|
68
|
+
color: mix($input-focus-border-color, black, 85%);
|
|
69
69
|
}
|
|
70
70
|
.neo-forms-editor {
|
|
71
71
|
border-bottom: 1px solid $input-focus-border-color;
|