@openmrs/esm-implementer-tools-app 4.0.3-pre.462 → 4.0.3

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.
@@ -1,64 +1,43 @@
1
- import React, { useState, useEffect, useMemo } from "react";
2
- import debounce from "lodash-es/debounce";
1
+ import React, { useState, useMemo } from "react";
2
+ import { useTranslation } from "react-i18next";
3
3
  import uniqueId from "lodash-es/uniqueId";
4
4
  import {
5
- fetchConceptByUuid,
6
- performConceptSearch,
7
- } from "./concept-search.resource";
8
- import styles from "./uuid-search.scss";
9
- import {
5
+ InlineLoading,
10
6
  Search,
11
7
  StructuredListCell,
12
8
  StructuredListRow,
13
9
  StructuredListWrapper,
10
+ Tile,
14
11
  } from "@carbon/react";
15
- import { useTranslation } from "react-i18next";
12
+ import { Concept, useConceptLookup } from "./concept-search.resource";
13
+ import styles from "./uuid-search.scss";
16
14
 
17
15
  interface ConceptSearchBoxProps {
18
- value: string;
19
16
  setConcept: (concept) => void;
17
+ value: string;
20
18
  }
21
19
 
22
20
  export function ConceptSearchBox({ setConcept, value }: ConceptSearchBoxProps) {
23
- const [searchTerm, setSearchTerm] = useState("");
24
- const [searchResults, setSearchResults] = useState([]);
25
- const [activeConceptUuid, setActiveConceptUuid] = useState<any>(value);
26
- const searchTimeoutInMs = 300;
27
21
  const { t } = useTranslation();
28
22
  const id = useMemo(() => uniqueId(), []);
23
+ const [conceptToLookup, setConceptToLookup] = useState("");
24
+ const [selectedConcept, setSelectedConcept] = useState<string>(value);
25
+ const { concepts, isSearchingConcepts } = useConceptLookup(conceptToLookup);
29
26
 
30
- const handleUuidChange = (concept) => {
31
- setActiveConceptUuid(concept.uuid);
32
- resetSearch();
33
- setConcept(concept);
27
+ const handleSearchTermChange = (event) => {
28
+ setConceptToLookup(event.target.value);
34
29
  };
35
30
 
36
- const resetSearch = () => {
37
- setSearchTerm("");
38
- setSearchResults([]);
31
+ const handleConceptUuidChange = (concept) => {
32
+ setSelectedConcept(concept.uuid);
33
+ setConcept(concept);
34
+ setConceptToLookup("");
39
35
  };
40
36
 
41
- const handleSearchTermChange = debounce((searchTerm) => {
42
- setSearchTerm(searchTerm);
43
- }, searchTimeoutInMs);
44
-
45
- useEffect(() => {
46
- const ac = new AbortController();
47
-
48
- if (searchTerm && searchTerm.length >= 2) {
49
- performConceptSearch(searchTerm).then(({ data: { results } }) => {
50
- setSearchResults(results.slice(0, 9));
51
- });
52
- } else {
53
- setSearchResults([]);
54
- }
55
- return () => ac.abort();
56
- }, [searchTerm]);
57
-
58
37
  return (
59
38
  <div>
60
- {activeConceptUuid && (
61
- <p className={styles.activeUuid}>{activeConceptUuid}</p>
39
+ {selectedConcept && (
40
+ <p className={styles.activeUuid}>{selectedConcept}</p>
62
41
  )}
63
42
  <div className={styles.autocomplete}>
64
43
  <Search
@@ -70,43 +49,55 @@ export function ConceptSearchBox({ setConcept, value }: ConceptSearchBoxProps) {
70
49
  autoCapitalize="off"
71
50
  aria-autocomplete="list"
72
51
  role="combobox"
73
- aria-label={t("searchConceptHelperText", "Concept Name")}
52
+ aria-label={t("searchConceptHelperText", "Search concepts")}
74
53
  aria-controls={`searchbox-${id}`}
75
- aria-expanded={searchResults.length > 0}
76
- placeholder={t("searchConceptHelperText", "Concept Name")}
77
- onChange={($event) => {
78
- handleSearchTermChange($event.target.value);
79
- }}
54
+ aria-expanded={concepts.length > 0}
55
+ placeholder={t("searchConceptHelperText", "Search concepts")}
56
+ onChange={handleSearchTermChange}
80
57
  />
81
- {!!searchResults.length && (
82
- <StructuredListWrapper
83
- selection
84
- id={`searchbox-${id}`}
85
- className={styles.listbox}
86
- >
87
- {searchResults.map((concept: any) => (
88
- <StructuredListRow
89
- key={concept.uuid}
90
- role="option"
91
- aria-selected="true"
58
+ {(() => {
59
+ if (!conceptToLookup) return null;
60
+ if (isSearchingConcepts)
61
+ return (
62
+ <InlineLoading
63
+ className={styles.loader}
64
+ description={t("searching", "Searching") + "..."}
65
+ />
66
+ );
67
+ if (concepts && concepts.length && !isSearchingConcepts) {
68
+ return (
69
+ <StructuredListWrapper
70
+ selection
71
+ id={`searchbox-${id}`}
72
+ className={styles.listbox}
92
73
  >
93
- <StructuredListCell
94
- onClick={() => {
95
- handleUuidChange(concept);
96
- }}
97
- className={styles.smallListCell}
98
- >
99
- {concept.display}
100
- </StructuredListCell>
101
- </StructuredListRow>
102
- ))}
103
- </StructuredListWrapper>
104
- )}
105
- {searchTerm && searchResults && !searchResults.length && (
106
- <p className={styles.bodyShort01}>
107
- {t("noConceptsFoundText", "No matching results found")}
108
- </p>
109
- )}
74
+ {concepts.map((concept: Concept) => (
75
+ <StructuredListRow
76
+ key={concept.uuid}
77
+ role="option"
78
+ aria-selected="true"
79
+ >
80
+ <StructuredListCell
81
+ onClick={() => {
82
+ handleConceptUuidChange(concept);
83
+ }}
84
+ className={styles.smallListCell}
85
+ >
86
+ {concept.display}
87
+ </StructuredListCell>
88
+ </StructuredListRow>
89
+ ))}
90
+ </StructuredListWrapper>
91
+ );
92
+ }
93
+ return (
94
+ <Tile className={styles.emptyResults}>
95
+ <span>
96
+ {t("noConceptsFoundText", "No matching concepts found")}
97
+ </span>
98
+ </Tile>
99
+ );
100
+ })()}
110
101
  </div>
111
102
  </div>
112
103
  );
@@ -23,3 +23,14 @@
23
23
  .smallListCell {
24
24
  padding: spacing.$spacing-03;
25
25
  }
26
+
27
+ .loader {
28
+ margin: 1rem;
29
+ }
30
+
31
+ .emptyResults {
32
+ @include type.type-style("body-compact-01");
33
+ background-color: $ui-02;
34
+ color: $text-02;
35
+ min-height: 1rem;
36
+ }
@@ -45,7 +45,7 @@ export function ValueEditorField({
45
45
  hideLabel
46
46
  labelText=""
47
47
  onChange={(event, { checked, id }) => onChange(checked)}
48
- ></Checkbox>
48
+ />
49
49
  ) : valueType === Type.ConceptUuid ? (
50
50
  <ConceptSearchBox
51
51
  value={value}
@@ -67,18 +67,16 @@ export function ValueEditorField({
67
67
  <NumberInput
68
68
  id={id}
69
69
  value={value}
70
- onChange={
71
- // e.target.value not working properly right now: https://github.com/carbon-design-system/carbon/issues/7457
72
- (e) => onChange(Number((e as any).imaginaryTarget.value))
73
- }
74
- ></NumberInput>
70
+ onChange={(e, { value }) => onChange(value ? parseInt(value) : 0)}
71
+ hideSteppers
72
+ />
75
73
  ) : valueType === Type.String || valueType === Type.UUID ? (
76
74
  <TextInput
77
75
  id={id}
78
76
  value={value}
79
77
  labelText=""
80
78
  onChange={(e) => onChange(e.target.value)}
81
- ></TextInput>
79
+ />
82
80
  ) : valueType === "add" ? (
83
81
  <ExtensionSlotAdd value={value ?? element._value} setValue={onChange} />
84
82
  ) : valueType === "remove" && path ? (