@openmrs/esm-styleguide 10.0.1-pre.5199 → 10.0.1-pre.5240
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/.turbo/turbo-build.log +1 -1
- package/dist/workspaces2/scope-utils.d.ts +1 -1
- package/dist/workspaces2/scope-utils.d.ts.map +1 -1
- package/dist/workspaces2/scope-utils.js +32 -5
- package/package.json +25 -25
- package/src/workspaces2/scope-utils.test.ts +111 -1
- package/src/workspaces2/scope-utils.ts +33 -5
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
[0] Successfully compiled: 123 files, copied 167 files with swc (
|
|
1
|
+
[0] Successfully compiled: 123 files, copied 167 files with swc (273.27ms)
|
|
2
2
|
[0] swc --strip-leading-paths --copy-files src -d dist && svgo -rf dist --quiet exited with code 0
|
|
3
3
|
[1] tsc --project tsconfig.build.json exited with code 0
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Determines whether workspaces should close based on a scope pattern and URL change.
|
|
3
3
|
*
|
|
4
|
-
* @param scopePattern - A regex pattern
|
|
4
|
+
* @param scopePattern - A regex pattern matched against the SPA-relative pathname. May include capture groups.
|
|
5
5
|
* @param oldUrl - The URL being navigated away from.
|
|
6
6
|
* @param newUrl - The URL being navigated to.
|
|
7
7
|
* @returns `true` if the workspace should close, `false` if it should stay open.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope-utils.d.ts","sourceRoot":"","sources":["../../src/workspaces2/scope-utils.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"scope-utils.d.ts","sourceRoot":"","sources":["../../src/workspaces2/scope-utils.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAqCpG"}
|
|
@@ -1,17 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Determines whether workspaces should close based on a scope pattern and URL change.
|
|
3
3
|
*
|
|
4
|
-
* @param scopePattern - A regex pattern
|
|
4
|
+
* @param scopePattern - A regex pattern matched against the SPA-relative pathname. May include capture groups.
|
|
5
5
|
* @param oldUrl - The URL being navigated away from.
|
|
6
6
|
* @param newUrl - The URL being navigated to.
|
|
7
7
|
* @returns `true` if the workspace should close, `false` if it should stay open.
|
|
8
8
|
*/ export function shouldCloseOnUrlChange(scopePattern, oldUrl, newUrl) {
|
|
9
9
|
try {
|
|
10
|
-
const oldPathname = new URL(oldUrl, window.location.origin).pathname;
|
|
11
|
-
const newPathname = new URL(newUrl, window.location.origin).pathname;
|
|
12
10
|
const regex = new RegExp(scopePattern);
|
|
13
|
-
const
|
|
14
|
-
const
|
|
11
|
+
const oldPathnames = getPathnames(oldUrl);
|
|
12
|
+
const newPathnames = getPathnames(newUrl);
|
|
13
|
+
if (oldPathnames.spaRelative === null || newPathnames.spaRelative === null) {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
// scopePattern is defined against the SPA-relative pathname. Fall back to
|
|
17
|
+
// the full pathnames when the relative pathnames don't both match, so that
|
|
18
|
+
// patterns containing the SPA base path also work.
|
|
19
|
+
let oldMatch = regex.exec(oldPathnames.spaRelative);
|
|
20
|
+
let newMatch = regex.exec(newPathnames.spaRelative);
|
|
21
|
+
if (!oldMatch || !newMatch) {
|
|
22
|
+
oldMatch = regex.exec(oldPathnames.full);
|
|
23
|
+
newMatch = regex.exec(newPathnames.full);
|
|
24
|
+
}
|
|
15
25
|
if (!oldMatch || !newMatch) {
|
|
16
26
|
// One or both URLs don't match the pattern - close workspace
|
|
17
27
|
return true;
|
|
@@ -28,3 +38,20 @@
|
|
|
28
38
|
return true;
|
|
29
39
|
}
|
|
30
40
|
}
|
|
41
|
+
function getPathnames(url) {
|
|
42
|
+
const full = new URL(url, window.location.origin).pathname;
|
|
43
|
+
const spaBasePathname = new URL(window.getOpenmrsSpaBase?.() ?? '/', window.location.origin).pathname;
|
|
44
|
+
const spaBase = spaBasePathname.endsWith('/') ? spaBasePathname.slice(0, -1) : spaBasePathname;
|
|
45
|
+
let spaRelative = null;
|
|
46
|
+
if (!spaBase) {
|
|
47
|
+
spaRelative = full;
|
|
48
|
+
} else if (spaBase === full) {
|
|
49
|
+
spaRelative = '/';
|
|
50
|
+
} else if (full.startsWith(`${spaBase}/`)) {
|
|
51
|
+
spaRelative = full.slice(spaBase.length);
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
full,
|
|
55
|
+
spaRelative
|
|
56
|
+
};
|
|
57
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openmrs/esm-styleguide",
|
|
3
|
-
"version": "10.0.1-pre.
|
|
3
|
+
"version": "10.0.1-pre.5240",
|
|
4
4
|
"license": "MPL-2.0",
|
|
5
5
|
"description": "The styleguide for OpenMRS SPA",
|
|
6
6
|
"module": "dist/internal.js",
|
|
@@ -77,18 +77,18 @@
|
|
|
77
77
|
"react-aria-components": "^1.7.1"
|
|
78
78
|
},
|
|
79
79
|
"peerDependencies": {
|
|
80
|
-
"@openmrs/esm-api": "^10.0.1-pre.
|
|
81
|
-
"@openmrs/esm-config": "^10.0.1-pre.
|
|
82
|
-
"@openmrs/esm-emr-api": "^10.0.1-pre.
|
|
83
|
-
"@openmrs/esm-error-handling": "^10.0.1-pre.
|
|
84
|
-
"@openmrs/esm-extensions": "^10.0.1-pre.
|
|
85
|
-
"@openmrs/esm-globals": "^10.0.1-pre.
|
|
86
|
-
"@openmrs/esm-navigation": "^10.0.1-pre.
|
|
87
|
-
"@openmrs/esm-react-utils": "^10.0.1-pre.
|
|
88
|
-
"@openmrs/esm-routes": "^10.0.1-pre.
|
|
89
|
-
"@openmrs/esm-state": "^10.0.1-pre.
|
|
90
|
-
"@openmrs/esm-translations": "^10.0.1-pre.
|
|
91
|
-
"@openmrs/esm-utils": "^10.0.1-pre.
|
|
80
|
+
"@openmrs/esm-api": "^10.0.1-pre.5240",
|
|
81
|
+
"@openmrs/esm-config": "^10.0.1-pre.5240",
|
|
82
|
+
"@openmrs/esm-emr-api": "^10.0.1-pre.5240",
|
|
83
|
+
"@openmrs/esm-error-handling": "^10.0.1-pre.5240",
|
|
84
|
+
"@openmrs/esm-extensions": "^10.0.1-pre.5240",
|
|
85
|
+
"@openmrs/esm-globals": "^10.0.1-pre.5240",
|
|
86
|
+
"@openmrs/esm-navigation": "^10.0.1-pre.5240",
|
|
87
|
+
"@openmrs/esm-react-utils": "^10.0.1-pre.5240",
|
|
88
|
+
"@openmrs/esm-routes": "^10.0.1-pre.5240",
|
|
89
|
+
"@openmrs/esm-state": "^10.0.1-pre.5240",
|
|
90
|
+
"@openmrs/esm-translations": "^10.0.1-pre.5240",
|
|
91
|
+
"@openmrs/esm-utils": "^10.0.1-pre.5240",
|
|
92
92
|
"dayjs": "1.x",
|
|
93
93
|
"i18next": "25.x",
|
|
94
94
|
"react": "18.x",
|
|
@@ -98,18 +98,18 @@
|
|
|
98
98
|
"swr": "2.x"
|
|
99
99
|
},
|
|
100
100
|
"devDependencies": {
|
|
101
|
-
"@openmrs/esm-api": "10.0.1-pre.
|
|
102
|
-
"@openmrs/esm-config": "10.0.1-pre.
|
|
103
|
-
"@openmrs/esm-emr-api": "10.0.1-pre.
|
|
104
|
-
"@openmrs/esm-error-handling": "10.0.1-pre.
|
|
105
|
-
"@openmrs/esm-extensions": "10.0.1-pre.
|
|
106
|
-
"@openmrs/esm-globals": "10.0.1-pre.
|
|
107
|
-
"@openmrs/esm-navigation": "10.0.1-pre.
|
|
108
|
-
"@openmrs/esm-react-utils": "10.0.1-pre.
|
|
109
|
-
"@openmrs/esm-routes": "10.0.1-pre.
|
|
110
|
-
"@openmrs/esm-state": "10.0.1-pre.
|
|
111
|
-
"@openmrs/esm-translations": "10.0.1-pre.
|
|
112
|
-
"@openmrs/esm-utils": "10.0.1-pre.
|
|
101
|
+
"@openmrs/esm-api": "10.0.1-pre.5240",
|
|
102
|
+
"@openmrs/esm-config": "10.0.1-pre.5240",
|
|
103
|
+
"@openmrs/esm-emr-api": "10.0.1-pre.5240",
|
|
104
|
+
"@openmrs/esm-error-handling": "10.0.1-pre.5240",
|
|
105
|
+
"@openmrs/esm-extensions": "10.0.1-pre.5240",
|
|
106
|
+
"@openmrs/esm-globals": "10.0.1-pre.5240",
|
|
107
|
+
"@openmrs/esm-navigation": "10.0.1-pre.5240",
|
|
108
|
+
"@openmrs/esm-react-utils": "10.0.1-pre.5240",
|
|
109
|
+
"@openmrs/esm-routes": "10.0.1-pre.5240",
|
|
110
|
+
"@openmrs/esm-state": "10.0.1-pre.5240",
|
|
111
|
+
"@openmrs/esm-translations": "10.0.1-pre.5240",
|
|
112
|
+
"@openmrs/esm-utils": "10.0.1-pre.5240",
|
|
113
113
|
"@swc/cli": "0.8.1",
|
|
114
114
|
"@swc/core": "1.15.21",
|
|
115
115
|
"@types/geopattern": "^1.2.9",
|
|
@@ -127,6 +127,116 @@ describe('shouldCloseOnUrlChange', () => {
|
|
|
127
127
|
],
|
|
128
128
|
['closes: relative URLs leaving scope', '^/home/appointments', '/home/appointments', '/home/service-queues', true],
|
|
129
129
|
])('%s', (_desc, pattern, oldUrl, newUrl, expected) => {
|
|
130
|
-
|
|
130
|
+
withSpaBase('/', () => {
|
|
131
|
+
expect(shouldCloseOnUrlChange(pattern, oldUrl, newUrl)).toBe(expected);
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it.each([
|
|
136
|
+
[
|
|
137
|
+
'stays open: navigation from the exact SPA base remains in a root scope',
|
|
138
|
+
'^/',
|
|
139
|
+
'http://localhost/openmrs/spa',
|
|
140
|
+
'http://localhost/openmrs/spa/home',
|
|
141
|
+
false,
|
|
142
|
+
],
|
|
143
|
+
[
|
|
144
|
+
'stays open: same patient under the configured SPA base',
|
|
145
|
+
'^/patient/([^/]+)/chart(?:/|$)',
|
|
146
|
+
'http://localhost/openmrs/spa/patient/abc-123/chart/vitals',
|
|
147
|
+
'http://localhost/openmrs/spa/patient/abc-123/chart/conditions',
|
|
148
|
+
false,
|
|
149
|
+
],
|
|
150
|
+
[
|
|
151
|
+
'closes: different patient under the configured SPA base',
|
|
152
|
+
'^/patient/([^/]+)/chart(?:/|$)',
|
|
153
|
+
'http://localhost/openmrs/spa/patient/abc-123/chart/vitals',
|
|
154
|
+
'http://localhost/openmrs/spa/patient/def-456/chart/vitals',
|
|
155
|
+
true,
|
|
156
|
+
],
|
|
157
|
+
[
|
|
158
|
+
'closes: route only shares the SPA base as a string prefix',
|
|
159
|
+
'^/patient/([^/]+)/chart(?:/|$)',
|
|
160
|
+
'http://localhost/openmrs/spa2/patient/abc-123/chart/vitals',
|
|
161
|
+
'http://localhost/openmrs/spa2/patient/abc-123/chart/conditions',
|
|
162
|
+
true,
|
|
163
|
+
],
|
|
164
|
+
[
|
|
165
|
+
'closes: navigation leaves the configured SPA base',
|
|
166
|
+
'^/patient/([^/]+)/chart(?:/|$)',
|
|
167
|
+
'http://localhost/openmrs/spa/patient/abc-123/chart/vitals',
|
|
168
|
+
'http://localhost/patient/abc-123/chart/conditions',
|
|
169
|
+
true,
|
|
170
|
+
],
|
|
171
|
+
[
|
|
172
|
+
'closes: route only shares the patient chart prefix',
|
|
173
|
+
'^/patient/([^/]+)/chart(?:/|$)',
|
|
174
|
+
'http://localhost/openmrs/spa/patient/abc-123/chart',
|
|
175
|
+
'http://localhost/openmrs/spa/patient/abc-123/chart-extra',
|
|
176
|
+
true,
|
|
177
|
+
],
|
|
178
|
+
[
|
|
179
|
+
'stays open: legacy pattern includes the configured SPA base',
|
|
180
|
+
'^/openmrs/spa/patient/([^/]+)/chart(?:/|$)',
|
|
181
|
+
'http://localhost/openmrs/spa/patient/abc-123/chart/vitals',
|
|
182
|
+
'http://localhost/openmrs/spa/patient/abc-123/chart/conditions',
|
|
183
|
+
false,
|
|
184
|
+
],
|
|
185
|
+
[
|
|
186
|
+
'stays open: legacy pattern matches both full pathnames when only one relative pathname matches',
|
|
187
|
+
'^/openmrs',
|
|
188
|
+
'http://localhost/openmrs/spa/home',
|
|
189
|
+
'http://localhost/openmrs/spa/openmrs-lab',
|
|
190
|
+
false,
|
|
191
|
+
],
|
|
192
|
+
[
|
|
193
|
+
'closes: legacy pattern captures a different patient',
|
|
194
|
+
'^/openmrs/spa/patient/([^/]+)/chart(?:/|$)',
|
|
195
|
+
'http://localhost/openmrs/spa/patient/abc-123/chart/vitals',
|
|
196
|
+
'http://localhost/openmrs/spa/patient/def-456/chart/vitals',
|
|
197
|
+
true,
|
|
198
|
+
],
|
|
199
|
+
])('%s', (_desc, pattern, oldUrl, newUrl, expected) => {
|
|
200
|
+
withSpaBase('/openmrs/spa/', () => {
|
|
201
|
+
expect(shouldCloseOnUrlChange(pattern, oldUrl, newUrl)).toBe(expected);
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it('matches against full pathnames when getOpenmrsSpaBase is not defined', () => {
|
|
206
|
+
const originalGetOpenmrsSpaBase = window.getOpenmrsSpaBase;
|
|
207
|
+
// @ts-expect-error simulating an environment without the app shell globals
|
|
208
|
+
delete window.getOpenmrsSpaBase;
|
|
209
|
+
|
|
210
|
+
try {
|
|
211
|
+
expect(shouldCloseOnUrlChange('^/home/appointments', '/home/appointments', '/home/appointments/details')).toBe(
|
|
212
|
+
false,
|
|
213
|
+
);
|
|
214
|
+
expect(shouldCloseOnUrlChange('^/home/appointments', '/home/appointments', '/home/service-queues')).toBe(true);
|
|
215
|
+
} finally {
|
|
216
|
+
window.getOpenmrsSpaBase = originalGetOpenmrsSpaBase;
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it('matches against a custom SPA base', () => {
|
|
221
|
+
withSpaBase('/custom/spa/', () => {
|
|
222
|
+
expect(
|
|
223
|
+
shouldCloseOnUrlChange(
|
|
224
|
+
'^/patient/([^/]+)/chart(?:/|$)',
|
|
225
|
+
'/custom/spa/patient/abc-123/chart/vitals',
|
|
226
|
+
'/custom/spa/patient/abc-123/chart/conditions',
|
|
227
|
+
),
|
|
228
|
+
).toBe(false);
|
|
229
|
+
});
|
|
131
230
|
});
|
|
132
231
|
});
|
|
232
|
+
|
|
233
|
+
function withSpaBase<T>(spaBase: string, callback: () => T): T {
|
|
234
|
+
const originalGetOpenmrsSpaBase = window.getOpenmrsSpaBase;
|
|
235
|
+
window.getOpenmrsSpaBase = () => spaBase;
|
|
236
|
+
|
|
237
|
+
try {
|
|
238
|
+
return callback();
|
|
239
|
+
} finally {
|
|
240
|
+
window.getOpenmrsSpaBase = originalGetOpenmrsSpaBase;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
@@ -1,19 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Determines whether workspaces should close based on a scope pattern and URL change.
|
|
3
3
|
*
|
|
4
|
-
* @param scopePattern - A regex pattern
|
|
4
|
+
* @param scopePattern - A regex pattern matched against the SPA-relative pathname. May include capture groups.
|
|
5
5
|
* @param oldUrl - The URL being navigated away from.
|
|
6
6
|
* @param newUrl - The URL being navigated to.
|
|
7
7
|
* @returns `true` if the workspace should close, `false` if it should stay open.
|
|
8
8
|
*/
|
|
9
9
|
export function shouldCloseOnUrlChange(scopePattern: string, oldUrl: string, newUrl: string): boolean {
|
|
10
10
|
try {
|
|
11
|
-
const oldPathname = new URL(oldUrl, window.location.origin).pathname;
|
|
12
|
-
const newPathname = new URL(newUrl, window.location.origin).pathname;
|
|
13
11
|
const regex = new RegExp(scopePattern);
|
|
12
|
+
const oldPathnames = getPathnames(oldUrl);
|
|
13
|
+
const newPathnames = getPathnames(newUrl);
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
if (oldPathnames.spaRelative === null || newPathnames.spaRelative === null) {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// scopePattern is defined against the SPA-relative pathname. Fall back to
|
|
20
|
+
// the full pathnames when the relative pathnames don't both match, so that
|
|
21
|
+
// patterns containing the SPA base path also work.
|
|
22
|
+
let oldMatch = regex.exec(oldPathnames.spaRelative);
|
|
23
|
+
let newMatch = regex.exec(newPathnames.spaRelative);
|
|
24
|
+
if (!oldMatch || !newMatch) {
|
|
25
|
+
oldMatch = regex.exec(oldPathnames.full);
|
|
26
|
+
newMatch = regex.exec(newPathnames.full);
|
|
27
|
+
}
|
|
17
28
|
|
|
18
29
|
if (!oldMatch || !newMatch) {
|
|
19
30
|
// One or both URLs don't match the pattern - close workspace
|
|
@@ -33,3 +44,20 @@ export function shouldCloseOnUrlChange(scopePattern: string, oldUrl: string, new
|
|
|
33
44
|
return true;
|
|
34
45
|
}
|
|
35
46
|
}
|
|
47
|
+
|
|
48
|
+
function getPathnames(url: string) {
|
|
49
|
+
const full = new URL(url, window.location.origin).pathname;
|
|
50
|
+
const spaBasePathname = new URL(window.getOpenmrsSpaBase?.() ?? '/', window.location.origin).pathname;
|
|
51
|
+
const spaBase = spaBasePathname.endsWith('/') ? spaBasePathname.slice(0, -1) : spaBasePathname;
|
|
52
|
+
let spaRelative: string | null = null;
|
|
53
|
+
|
|
54
|
+
if (!spaBase) {
|
|
55
|
+
spaRelative = full;
|
|
56
|
+
} else if (spaBase === full) {
|
|
57
|
+
spaRelative = '/';
|
|
58
|
+
} else if (full.startsWith(`${spaBase}/`)) {
|
|
59
|
+
spaRelative = full.slice(spaBase.length);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return { full, spaRelative };
|
|
63
|
+
}
|