@openmrs/esm-styleguide 8.0.1-pre.3511 → 8.0.1-pre.3525
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 +3 -3
- package/dist/location-picker/location-picker.resource.d.ts +1 -0
- package/dist/openmrs-esm-styleguide.css +1 -1
- package/dist/openmrs-esm-styleguide.css.map +1 -1
- package/dist/openmrs-esm-styleguide.js +2 -2
- package/dist/openmrs-esm-styleguide.js.map +1 -1
- package/package.json +15 -13
- package/src/location-picker/location-picker.component.tsx +50 -24
- package/src/location-picker/location-picker.module.scss +4 -17
- package/src/location-picker/location-picker.resource.ts +4 -13
- package/src/location-picker/location-picker.test.tsx +347 -51
- package/dist/brand.d.ts +0 -1
- package/dist/breakpoints/index.d.ts +0 -11
- package/dist/config-schema.d.ts +0 -23
- package/dist/custom-overflow-menu/custom-overflow-menu.component.d.ts +0 -8
- package/dist/custom-overflow-menu/index.d.ts +0 -1
- package/dist/datepicker/DatePickerIcon.d.ts +0 -6
- package/dist/datepicker/DatePickerInput.d.ts +0 -11
- package/dist/datepicker/MonthYear.d.ts +0 -10
- package/dist/datepicker/locale-context.d.ts +0 -2
- package/dist/datepicker/utils.d.ts +0 -15
- package/dist/error-state/error-state.component.d.ts +0 -6
- package/dist/error-state/index.d.ts +0 -1
- package/dist/icons/icon-registration.d.ts +0 -1
- package/dist/icons/icons.d.ts +0 -329
- package/dist/icons/index.d.ts +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/left-nav/index.d.ts +0 -23
- package/dist/logo/index.d.ts +0 -1
- package/dist/modals/index.d.ts +0 -25
- package/dist/notifications/actionable-notification.component.d.ts +0 -20
- package/dist/notifications/active-actionable-notifications.component.d.ts +0 -8
- package/dist/notifications/active-notifications.component.d.ts +0 -8
- package/dist/notifications/index.d.ts +0 -19
- package/dist/notifications/notification.component.d.ts +0 -19
- package/dist/pictograms/pictogram-registration.d.ts +0 -1
- package/dist/pictograms/pictograms.d.ts +0 -64
- package/dist/snackbars/active-snackbar.component.d.ts +0 -9
- package/dist/snackbars/index.d.ts +0 -12
- package/dist/snackbars/snackbar.component.d.ts +0 -22
- package/dist/svg-utils.d.ts +0 -1
- package/dist/toasts/active-toasts.component.d.ts +0 -9
- package/dist/toasts/index.d.ts +0 -12
- package/dist/toasts/toast.component.d.ts +0 -19
- package/dist/utils.d.ts +0 -6
- package/dist/workspaces/action-menu-button/action-menu-button.component.d.ts +0 -11
- package/dist/workspaces/container/action-menu.component.d.ts +0 -9
- package/dist/workspaces/container/workspace-container.component.d.ts +0 -54
- package/dist/workspaces/container/workspace-renderer.component.d.ts +0 -8
- package/dist/workspaces/notification/workspace-notification.component.d.ts +0 -6
- package/dist/workspaces/public.d.ts +0 -4
- package/dist/workspaces/workspace-sidebar-store/useWorkspaceGroupStore.d.ts +0 -11
- package/dist/workspaces/workspaces.d.ts +0 -236
- package/dist/workspaces2/workspace2-close-prompt.modal.d.ts +0 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openmrs/esm-styleguide",
|
|
3
|
-
"version": "8.0.1-pre.
|
|
3
|
+
"version": "8.0.1-pre.3525",
|
|
4
4
|
"license": "MPL-2.0",
|
|
5
5
|
"description": "The styleguide for OpenMRS SPA",
|
|
6
6
|
"main": "dist/openmrs-esm-styleguide.js",
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"scripts": {
|
|
38
38
|
"test": "cross-env TZ=UTC vitest run --passWithNoTests",
|
|
39
39
|
"test:watch": "cross-env TZ=UTC vitest watch",
|
|
40
|
+
"coverage": "cross-env TZ=UTC vitest run --coverage --passWithNoTests",
|
|
40
41
|
"build": "concurrently \"rspack --mode=production\" \"tsc --project tsconfig.build.json\"",
|
|
41
42
|
"build:development": "concurrently \"rspack --mode=development\" \"tsc --project tsconfig.build.json\"",
|
|
42
43
|
"analyze": "rspack --mode=production --env analyze=true",
|
|
@@ -97,20 +98,21 @@
|
|
|
97
98
|
"swr": "2.x"
|
|
98
99
|
},
|
|
99
100
|
"devDependencies": {
|
|
100
|
-
"@openmrs/esm-api": "8.0.1-pre.
|
|
101
|
-
"@openmrs/esm-config": "8.0.1-pre.
|
|
102
|
-
"@openmrs/esm-emr-api": "8.0.1-pre.
|
|
103
|
-
"@openmrs/esm-error-handling": "8.0.1-pre.
|
|
104
|
-
"@openmrs/esm-extensions": "8.0.1-pre.
|
|
105
|
-
"@openmrs/esm-globals": "8.0.1-pre.
|
|
106
|
-
"@openmrs/esm-navigation": "8.0.1-pre.
|
|
107
|
-
"@openmrs/esm-react-utils": "8.0.1-pre.
|
|
108
|
-
"@openmrs/esm-state": "8.0.1-pre.
|
|
109
|
-
"@openmrs/esm-translations": "8.0.1-pre.
|
|
110
|
-
"@openmrs/esm-utils": "8.0.1-pre.
|
|
101
|
+
"@openmrs/esm-api": "8.0.1-pre.3525",
|
|
102
|
+
"@openmrs/esm-config": "8.0.1-pre.3525",
|
|
103
|
+
"@openmrs/esm-emr-api": "8.0.1-pre.3525",
|
|
104
|
+
"@openmrs/esm-error-handling": "8.0.1-pre.3525",
|
|
105
|
+
"@openmrs/esm-extensions": "8.0.1-pre.3525",
|
|
106
|
+
"@openmrs/esm-globals": "8.0.1-pre.3525",
|
|
107
|
+
"@openmrs/esm-navigation": "8.0.1-pre.3525",
|
|
108
|
+
"@openmrs/esm-react-utils": "8.0.1-pre.3525",
|
|
109
|
+
"@openmrs/esm-state": "8.0.1-pre.3525",
|
|
110
|
+
"@openmrs/esm-translations": "8.0.1-pre.3525",
|
|
111
|
+
"@openmrs/esm-utils": "8.0.1-pre.3525",
|
|
111
112
|
"@rspack/cli": "^1.3.11",
|
|
112
113
|
"@rspack/core": "^1.3.11",
|
|
113
114
|
"@types/geopattern": "^1.2.9",
|
|
115
|
+
"@vitest/coverage-v8": "^4.0.7",
|
|
114
116
|
"concurrently": "^9.1.2",
|
|
115
117
|
"cross-env": "^7.0.3",
|
|
116
118
|
"happy-dom": "^17.4.7",
|
|
@@ -124,7 +126,7 @@
|
|
|
124
126
|
"svgo-loader": "^4.0.0",
|
|
125
127
|
"swr": "2.2.5",
|
|
126
128
|
"typescript": "^5.8.3",
|
|
127
|
-
"vitest": "^
|
|
129
|
+
"vitest": "^4.0.7"
|
|
128
130
|
},
|
|
129
131
|
"stableVersion": "8.0.0"
|
|
130
132
|
}
|
|
@@ -1,5 +1,12 @@
|
|
|
1
|
-
import React, { useCallback, useMemo, useState } from 'react';
|
|
2
|
-
import {
|
|
1
|
+
import React, { useCallback, useId, useMemo, useState } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
InlineLoading,
|
|
4
|
+
InlineNotification,
|
|
5
|
+
RadioButton,
|
|
6
|
+
RadioButtonGroup,
|
|
7
|
+
RadioButtonSkeleton,
|
|
8
|
+
Search,
|
|
9
|
+
} from '@carbon/react';
|
|
3
10
|
import { getCoreTranslation } from '@openmrs/esm-translations';
|
|
4
11
|
import { useOnVisible } from '@openmrs/esm-framework';
|
|
5
12
|
import { useLocationByUuid, useLocations } from './location-picker.resource';
|
|
@@ -20,7 +27,8 @@ export const LocationPicker: React.FC<LocationPickerProps> = ({
|
|
|
20
27
|
locationsPerRequest = 50,
|
|
21
28
|
onChange,
|
|
22
29
|
}) => {
|
|
23
|
-
const [searchTerm, setSearchTerm] = useState
|
|
30
|
+
const [searchTerm, setSearchTerm] = useState('');
|
|
31
|
+
const searchId = useId();
|
|
24
32
|
|
|
25
33
|
const { location: defaultLocation } = useLocationByUuid(defaultLocationUuid);
|
|
26
34
|
|
|
@@ -29,55 +37,69 @@ export const LocationPicker: React.FC<LocationPickerProps> = ({
|
|
|
29
37
|
isLoading,
|
|
30
38
|
hasMore,
|
|
31
39
|
loadingNewData,
|
|
40
|
+
error,
|
|
32
41
|
setPage,
|
|
33
42
|
} = useLocations(locationTag, locationsPerRequest, searchTerm);
|
|
34
43
|
|
|
35
44
|
const locations = useMemo(() => {
|
|
36
45
|
if (defaultLocation && !searchTerm && defaultLocationUuid) {
|
|
37
|
-
return [defaultLocation, ...fetchedLocations
|
|
46
|
+
return [defaultLocation, ...fetchedLocations.filter(({ resource }) => resource.id !== defaultLocationUuid)];
|
|
38
47
|
}
|
|
39
|
-
return fetchedLocations;
|
|
48
|
+
return fetchedLocations ?? [];
|
|
40
49
|
}, [defaultLocation, fetchedLocations, defaultLocationUuid, searchTerm]);
|
|
41
50
|
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
51
|
+
const handleSearchChange = useCallback(
|
|
52
|
+
(searchQuery: string) => {
|
|
53
|
+
onChange();
|
|
54
|
+
setSearchTerm(searchQuery.trim());
|
|
55
|
+
},
|
|
56
|
+
[onChange],
|
|
57
|
+
);
|
|
46
58
|
|
|
47
59
|
const loadMore = useCallback(() => {
|
|
48
60
|
if (loadingNewData || !hasMore) {
|
|
49
61
|
return;
|
|
50
|
-
} else {
|
|
51
|
-
setPage((page) => page + 1);
|
|
52
62
|
}
|
|
63
|
+
setPage((page) => page + 1);
|
|
53
64
|
}, [loadingNewData, hasMore, setPage]);
|
|
54
65
|
|
|
55
66
|
const loadingIconRef = useOnVisible(loadMore);
|
|
56
67
|
|
|
57
|
-
const
|
|
68
|
+
const infiniteScrollTriggerIndex = hasMore ? Math.max(0, Math.floor(locations.length - locationsPerRequest / 2)) : -1;
|
|
58
69
|
|
|
59
70
|
return (
|
|
60
|
-
|
|
71
|
+
<>
|
|
61
72
|
<Search
|
|
73
|
+
aria-describedby={error ? `${searchId}-error` : undefined}
|
|
62
74
|
labelText={getCoreTranslation('searchForLocation')}
|
|
63
|
-
id=
|
|
75
|
+
id={searchId}
|
|
64
76
|
placeholder={getCoreTranslation('searchForLocation')}
|
|
65
|
-
onChange={(event) =>
|
|
77
|
+
onChange={(event) => handleSearchChange(event.target.value)}
|
|
66
78
|
size="lg"
|
|
67
79
|
/>
|
|
80
|
+
{error && (
|
|
81
|
+
<div className={styles.errorNotification} id={`${searchId}-error`}>
|
|
82
|
+
<InlineNotification
|
|
83
|
+
kind="error"
|
|
84
|
+
subtitle={getCoreTranslation(
|
|
85
|
+
'errorLoadingLoginLocations',
|
|
86
|
+
'Unable to load login locations. Please try again or contact support if the problem persists.',
|
|
87
|
+
)}
|
|
88
|
+
title={getCoreTranslation('error', 'Error')}
|
|
89
|
+
/>
|
|
90
|
+
</div>
|
|
91
|
+
)}
|
|
68
92
|
<div className={styles.searchResults}>
|
|
69
93
|
{isLoading ? (
|
|
70
94
|
<div className={styles.loadingContainer}>
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
<RadioButtonSkeleton className={styles.radioButtonSkeleton} role="progressbar" />
|
|
75
|
-
<RadioButtonSkeleton className={styles.radioButtonSkeleton} role="progressbar" />
|
|
95
|
+
{Array.from({ length: 5 }).map((_, index) => (
|
|
96
|
+
<RadioButtonSkeleton key={index} className={styles.radioButtonSkeleton} role="progressbar" />
|
|
97
|
+
))}
|
|
76
98
|
</div>
|
|
77
99
|
) : (
|
|
78
100
|
<>
|
|
79
101
|
<div className={styles.locationResultsContainer}>
|
|
80
|
-
{locations
|
|
102
|
+
{locations.length > 0 ? (
|
|
81
103
|
<RadioButtonGroup
|
|
82
104
|
name="loginLocations"
|
|
83
105
|
onChange={(value) => {
|
|
@@ -89,10 +111,14 @@ export const LocationPicker: React.FC<LocationPickerProps> = ({
|
|
|
89
111
|
{locations.map((entry, i) => (
|
|
90
112
|
<RadioButton
|
|
91
113
|
className={styles.locationRadioButton}
|
|
92
|
-
key={entry.resource.id}
|
|
93
114
|
id={entry.resource.id}
|
|
115
|
+
key={entry.resource.id}
|
|
116
|
+
labelText={
|
|
117
|
+
<span ref={i === infiniteScrollTriggerIndex ? loadingIconRef : null}>
|
|
118
|
+
{entry.resource.name}
|
|
119
|
+
</span>
|
|
120
|
+
}
|
|
94
121
|
name={entry.resource.name}
|
|
95
|
-
labelText={<span ref={i === reloadIndex ? loadingIconRef : null}>{entry.resource.name}</span>}
|
|
96
122
|
value={entry.resource.id}
|
|
97
123
|
/>
|
|
98
124
|
))}
|
|
@@ -111,6 +137,6 @@ export const LocationPicker: React.FC<LocationPickerProps> = ({
|
|
|
111
137
|
</>
|
|
112
138
|
)}
|
|
113
139
|
</div>
|
|
114
|
-
|
|
140
|
+
</>
|
|
115
141
|
);
|
|
116
142
|
};
|
|
@@ -15,11 +15,6 @@
|
|
|
15
15
|
height: 25.5rem;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
.resultsCount {
|
|
19
|
-
@extend .bodyCompact01;
|
|
20
|
-
color: $color-gray-70;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
18
|
.locationResultsContainer {
|
|
24
19
|
display: flex;
|
|
25
20
|
overflow-y: auto;
|
|
@@ -39,18 +34,6 @@
|
|
|
39
34
|
margin-bottom: layout.$spacing-05;
|
|
40
35
|
}
|
|
41
36
|
|
|
42
|
-
.confirmButton {
|
|
43
|
-
padding: layout.$spacing-06;
|
|
44
|
-
|
|
45
|
-
.savePreferenceCheckbox {
|
|
46
|
-
padding-bottom: layout.$spacing-05 !important;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
button {
|
|
50
|
-
width: 100%;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
37
|
.radioButtonSkeleton {
|
|
55
38
|
margin-right: 0 !important;
|
|
56
39
|
margin-bottom: layout.$spacing-07;
|
|
@@ -82,3 +65,7 @@
|
|
|
82
65
|
justify-content: center;
|
|
83
66
|
margin: layout.$spacing-06 auto 0;
|
|
84
67
|
}
|
|
68
|
+
|
|
69
|
+
.errorNotification {
|
|
70
|
+
margin: layout.$spacing-03 0;
|
|
71
|
+
}
|
|
@@ -5,7 +5,6 @@ import useSwrInfinite from 'swr/infinite';
|
|
|
5
5
|
import { type FetchResponse, fhirBaseUrl, openmrsFetch } from '@openmrs/esm-api';
|
|
6
6
|
import { type FHIRLocationResource } from '@openmrs/esm-emr-api';
|
|
7
7
|
import { useDebounce } from '@openmrs/esm-react-utils';
|
|
8
|
-
import { showNotification } from '../notifications';
|
|
9
8
|
|
|
10
9
|
export interface LocationResponse {
|
|
11
10
|
type: string;
|
|
@@ -27,6 +26,7 @@ export interface LoginLocationData {
|
|
|
27
26
|
totalResults?: number;
|
|
28
27
|
hasMore: boolean;
|
|
29
28
|
loadingNewData: boolean;
|
|
29
|
+
error: Error | null;
|
|
30
30
|
setPage: (size: number | ((_size: number) => number)) => Promise<FetchResponse<LocationResponse>[] | undefined>;
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -53,7 +53,6 @@ export function useLocationByUuid(locationUuid?: string) {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
export function useLocations(locationTag?: string, count: number = 0, searchQuery: string = ''): LoginLocationData {
|
|
56
|
-
const { t } = useTranslation();
|
|
57
56
|
const debouncedSearchQuery = useDebounce(searchQuery);
|
|
58
57
|
function constructUrl(page: number, prevPageData: FetchResponse<LocationResponse>) {
|
|
59
58
|
if (prevPageData) {
|
|
@@ -92,7 +91,7 @@ export function useLocations(locationTag?: string, count: number = 0, searchQuer
|
|
|
92
91
|
urlSearchParameters.append('_tag', locationTag);
|
|
93
92
|
}
|
|
94
93
|
|
|
95
|
-
if (typeof debouncedSearchQuery === 'string' && debouncedSearchQuery
|
|
94
|
+
if (typeof debouncedSearchQuery === 'string' && debouncedSearchQuery !== '') {
|
|
96
95
|
urlSearchParameters.append('name:contains', debouncedSearchQuery);
|
|
97
96
|
}
|
|
98
97
|
|
|
@@ -104,15 +103,6 @@ export function useLocations(locationTag?: string, count: number = 0, searchQuer
|
|
|
104
103
|
openmrsFetch,
|
|
105
104
|
);
|
|
106
105
|
|
|
107
|
-
if (error) {
|
|
108
|
-
showNotification({
|
|
109
|
-
title: t('errorLoadingLoginLocations', 'Error loading login locations'),
|
|
110
|
-
kind: 'error',
|
|
111
|
-
critical: true,
|
|
112
|
-
description: error?.message,
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
|
|
116
106
|
const memoizedLocations = useMemo(() => {
|
|
117
107
|
return {
|
|
118
108
|
locations: data?.length ? data?.flatMap((entries) => entries?.data?.entry ?? []) : [],
|
|
@@ -120,9 +110,10 @@ export function useLocations(locationTag?: string, count: number = 0, searchQuer
|
|
|
120
110
|
totalResults: data?.[0]?.data?.total,
|
|
121
111
|
hasMore: data?.length ? data?.[data.length - 1]?.data?.link?.some((link) => link.relation === 'next') : false,
|
|
122
112
|
loadingNewData: isValidating,
|
|
113
|
+
error: error || null,
|
|
123
114
|
setPage: setSize,
|
|
124
115
|
};
|
|
125
|
-
}, [isLoading, data, isValidating, setSize]);
|
|
116
|
+
}, [isLoading, data, isValidating, setSize, error]);
|
|
126
117
|
|
|
127
118
|
return memoizedLocations;
|
|
128
119
|
}
|