@visns-studio/visns-components 4.5.7 → 4.5.8
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,4 +1,4 @@
|
|
|
1
|
-
import React, { useEffect, useState } from 'react';
|
|
1
|
+
import React, { useEffect, useRef, useState, useCallback } from 'react';
|
|
2
2
|
import { Link, useLocation, useNavigate } from 'react-router-dom';
|
|
3
3
|
import {
|
|
4
4
|
ArrowCycle,
|
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
Person,
|
|
32
32
|
Question,
|
|
33
33
|
QuestionFill,
|
|
34
|
+
Search,
|
|
34
35
|
SettingsVertical,
|
|
35
36
|
ShippingBoxV1,
|
|
36
37
|
SignOut,
|
|
@@ -44,16 +45,178 @@ import CustomFetch from './Fetch';
|
|
|
44
45
|
import Notification from './Notification';
|
|
45
46
|
import styles from './styles/Navigation.module.css';
|
|
46
47
|
|
|
48
|
+
const SearchComponent = ({
|
|
49
|
+
navigate,
|
|
50
|
+
search,
|
|
51
|
+
setSearch,
|
|
52
|
+
searchResultShow,
|
|
53
|
+
searchResult,
|
|
54
|
+
setSearchResultShow,
|
|
55
|
+
setSearchResult,
|
|
56
|
+
navConfig,
|
|
57
|
+
}) => {
|
|
58
|
+
const searchWrapperRef = useRef(null);
|
|
59
|
+
|
|
60
|
+
const handleClickSearch = (url) => {
|
|
61
|
+
if (url) {
|
|
62
|
+
setSearchResultShow(false);
|
|
63
|
+
navigate(url);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const handleKeyPress = (e) => {
|
|
68
|
+
if (e.key === 'Enter') {
|
|
69
|
+
fetchSearchResult();
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const handleSearch = (e) => {
|
|
74
|
+
e.preventDefault();
|
|
75
|
+
fetchSearchResult();
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const handleSearchChange = (e) => {
|
|
79
|
+
setSearch(e.target.value);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const fetchSearchResult = useCallback(async () => {
|
|
83
|
+
try {
|
|
84
|
+
if (search.trim() === '') {
|
|
85
|
+
setSearchResultShow(false);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const res = await CustomFetch(navConfig.search.url, 'POST', {
|
|
90
|
+
search,
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
if (res.data) {
|
|
94
|
+
const updatedSearchResult = searchResult.map((searchItem) => {
|
|
95
|
+
const newData = res.data[searchItem.id] || [];
|
|
96
|
+
return {
|
|
97
|
+
...searchItem,
|
|
98
|
+
data: newData,
|
|
99
|
+
};
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
setSearchResult(updatedSearchResult);
|
|
103
|
+
setSearchResultShow(true);
|
|
104
|
+
}
|
|
105
|
+
} catch (err) {
|
|
106
|
+
console.error(err);
|
|
107
|
+
}
|
|
108
|
+
}, [
|
|
109
|
+
search,
|
|
110
|
+
navConfig.search.url,
|
|
111
|
+
searchResult,
|
|
112
|
+
setSearchResult,
|
|
113
|
+
setSearchResultShow,
|
|
114
|
+
]);
|
|
115
|
+
|
|
116
|
+
useEffect(() => {
|
|
117
|
+
const handleClickOutside = (event) => {
|
|
118
|
+
if (
|
|
119
|
+
searchWrapperRef.current &&
|
|
120
|
+
!searchWrapperRef.current.contains(event.target)
|
|
121
|
+
) {
|
|
122
|
+
setSearchResultShow(false);
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
127
|
+
return () => {
|
|
128
|
+
document.removeEventListener('mousedown', handleClickOutside);
|
|
129
|
+
};
|
|
130
|
+
}, [searchWrapperRef, setSearchResultShow]);
|
|
131
|
+
|
|
132
|
+
const getNestedValues = (obj, keys) => {
|
|
133
|
+
return keys
|
|
134
|
+
.map((key) => obj[key])
|
|
135
|
+
.filter((value) => value)
|
|
136
|
+
.join(' ');
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
return (
|
|
140
|
+
<div className={styles.globalsearch} ref={searchWrapperRef}>
|
|
141
|
+
<input
|
|
142
|
+
type="text"
|
|
143
|
+
placeholder="Search"
|
|
144
|
+
value={search}
|
|
145
|
+
onChange={handleSearchChange}
|
|
146
|
+
onKeyDown={handleKeyPress}
|
|
147
|
+
/>
|
|
148
|
+
{searchResultShow && (
|
|
149
|
+
<ul
|
|
150
|
+
className={styles['AutocompletePlace-results']}
|
|
151
|
+
style={{ marginTop: '40px' }}
|
|
152
|
+
>
|
|
153
|
+
{searchResult.length > 0 &&
|
|
154
|
+
searchResult.map(
|
|
155
|
+
(searchItem, searchItemKey) =>
|
|
156
|
+
searchItem.data.length > 0 && (
|
|
157
|
+
<React.Fragment
|
|
158
|
+
key={`search-category-${searchItem.id}-${searchItemKey}`}
|
|
159
|
+
>
|
|
160
|
+
<li
|
|
161
|
+
className={
|
|
162
|
+
styles[
|
|
163
|
+
'AutocompletePlace-items'
|
|
164
|
+
]
|
|
165
|
+
}
|
|
166
|
+
>
|
|
167
|
+
<strong>{searchItem.label}</strong>
|
|
168
|
+
</li>
|
|
169
|
+
<ul>
|
|
170
|
+
{searchItem.data.map((item) => (
|
|
171
|
+
<li
|
|
172
|
+
key={`${searchItemKey}-${item.id}`}
|
|
173
|
+
className={
|
|
174
|
+
styles[
|
|
175
|
+
'AutocompletePlace-items'
|
|
176
|
+
]
|
|
177
|
+
}
|
|
178
|
+
onClick={() => {
|
|
179
|
+
handleClickSearch(
|
|
180
|
+
`${searchItem.url}${item.id}`
|
|
181
|
+
);
|
|
182
|
+
}}
|
|
183
|
+
data-type={searchItem.id}
|
|
184
|
+
data-id={item.id}
|
|
185
|
+
>
|
|
186
|
+
{getNestedValues(
|
|
187
|
+
item,
|
|
188
|
+
searchItem.key
|
|
189
|
+
)}
|
|
190
|
+
</li>
|
|
191
|
+
))}
|
|
192
|
+
</ul>
|
|
193
|
+
</React.Fragment>
|
|
194
|
+
)
|
|
195
|
+
)}
|
|
196
|
+
</ul>
|
|
197
|
+
)}
|
|
198
|
+
<button onClick={handleSearch}>
|
|
199
|
+
<Search strokeWidth={2} size={36} />
|
|
200
|
+
</button>
|
|
201
|
+
</div>
|
|
202
|
+
);
|
|
203
|
+
};
|
|
204
|
+
|
|
47
205
|
function Navigation({
|
|
48
206
|
children,
|
|
49
207
|
layout = 'full',
|
|
50
208
|
logo,
|
|
51
209
|
navConfig,
|
|
52
|
-
searchComponent,
|
|
53
210
|
setSystemAuth,
|
|
54
211
|
themeType,
|
|
55
212
|
userProfile,
|
|
56
213
|
}) {
|
|
214
|
+
const [search, setSearch] = useState('');
|
|
215
|
+
const [searchResultShow, setSearchResultShow] = useState(false);
|
|
216
|
+
const [searchResult, setSearchResult] = useState(
|
|
217
|
+
navConfig.search?.tables || []
|
|
218
|
+
);
|
|
219
|
+
|
|
57
220
|
const location = useLocation();
|
|
58
221
|
const navigate = useNavigate();
|
|
59
222
|
const currentPage = location.pathname.substr(1) || 'dashboard';
|
|
@@ -61,7 +224,6 @@ function Navigation({
|
|
|
61
224
|
const [isScrolled, setIsScrolled] = useState(false);
|
|
62
225
|
const [navData, setNavData] = useState(navConfig);
|
|
63
226
|
|
|
64
|
-
// const appNavClasses = isScrolled ? styles['app-nav'] : styles['app-nav'];
|
|
65
227
|
const appNavClasses = styles['app-nav'];
|
|
66
228
|
|
|
67
229
|
const handleLogout = () => {
|
|
@@ -150,6 +312,7 @@ function Navigation({
|
|
|
150
312
|
peopleMultiple: PeopleMultiple,
|
|
151
313
|
question: Question,
|
|
152
314
|
questionFill: QuestionFill,
|
|
315
|
+
search: Search,
|
|
153
316
|
settingsVertical: SettingsVertical,
|
|
154
317
|
signOut: SignOut,
|
|
155
318
|
shippingBoxV1: ShippingBoxV1,
|
|
@@ -160,6 +323,7 @@ function Navigation({
|
|
|
160
323
|
};
|
|
161
324
|
|
|
162
325
|
const IconComponent = iconComponents[n.icon];
|
|
326
|
+
|
|
163
327
|
let navItemClasses;
|
|
164
328
|
|
|
165
329
|
if (n.class.includes('active')) {
|
|
@@ -366,7 +530,19 @@ function Navigation({
|
|
|
366
530
|
</aside>
|
|
367
531
|
<main className={styles.content}>
|
|
368
532
|
<div className={styles['content-header']}>
|
|
369
|
-
{
|
|
533
|
+
{navConfig.search?.enable === true && (
|
|
534
|
+
<SearchComponent
|
|
535
|
+
navigate={navigate}
|
|
536
|
+
search={search}
|
|
537
|
+
setSearch={setSearch}
|
|
538
|
+
searchResultShow={searchResultShow}
|
|
539
|
+
searchResult={searchResult}
|
|
540
|
+
setSearchResultShow={setSearchResultShow}
|
|
541
|
+
setSearchResult={setSearchResult}
|
|
542
|
+
navConfig={navConfig}
|
|
543
|
+
/>
|
|
544
|
+
)}
|
|
545
|
+
|
|
370
546
|
<div className={styles['content-title']}>
|
|
371
547
|
<button
|
|
372
548
|
className={
|
|
@@ -900,3 +900,79 @@
|
|
|
900
900
|
padding: 0 1rem;
|
|
901
901
|
}
|
|
902
902
|
}
|
|
903
|
+
|
|
904
|
+
.globalsearch {
|
|
905
|
+
display: flex;
|
|
906
|
+
flex-wrap: nowrap;
|
|
907
|
+
align-content: center;
|
|
908
|
+
width: 50%;
|
|
909
|
+
|
|
910
|
+
button {
|
|
911
|
+
width: max-content;
|
|
912
|
+
padding: 0.15rem 0.65rem;
|
|
913
|
+
margin: 0 0.5rem;
|
|
914
|
+
border: none;
|
|
915
|
+
background: var(--primary-color);
|
|
916
|
+
appearance: none;
|
|
917
|
+
border-radius: 0.375rem;
|
|
918
|
+
|
|
919
|
+
svg {
|
|
920
|
+
display: block;
|
|
921
|
+
color: white;
|
|
922
|
+
width: 100%;
|
|
923
|
+
max-width: 20px;
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
.AutocompletePlace-results {
|
|
929
|
+
z-index: 999;
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
.AutocompletePlace {
|
|
933
|
+
position: relative;
|
|
934
|
+
|
|
935
|
+
> svg {
|
|
936
|
+
position: absolute;
|
|
937
|
+
right: 0.5em;
|
|
938
|
+
top: 0.5em;
|
|
939
|
+
color: var(--paragraph-color);
|
|
940
|
+
cursor: pointer;
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
.toggleActive {
|
|
944
|
+
color: var(--highlight-color);
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
.AutocompletePlace-input {
|
|
949
|
+
padding: 0.65rem 3rem 0.65rem 0.95rem !important;
|
|
950
|
+
height: 38px;
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
.AutocompletePlace-results {
|
|
954
|
+
width: 400px;
|
|
955
|
+
position: absolute;
|
|
956
|
+
background-color: white;
|
|
957
|
+
padding: 0;
|
|
958
|
+
margin: 0;
|
|
959
|
+
border: 1px solid rgba(var(--primary-color), 0.25);
|
|
960
|
+
border-radius: var(--br);
|
|
961
|
+
overflow: hidden;
|
|
962
|
+
|
|
963
|
+
ul {
|
|
964
|
+
padding: 0;
|
|
965
|
+
margin: 0;
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
.AutocompletePlace-items {
|
|
970
|
+
list-style: none;
|
|
971
|
+
border-bottom: 1px solid rgba(var(--primary-color-rgb), 0.1);
|
|
972
|
+
cursor: pointer;
|
|
973
|
+
padding: 10px 10px;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
.AutocompletePlace-items:hover {
|
|
977
|
+
background-color: rgba(var(--paragraph-color-rgb), 0.065);
|
|
978
|
+
}
|
package/package.json
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"axios": "^1.7.2",
|
|
15
15
|
"dayjs": "^1.11.12",
|
|
16
16
|
"file-saver": "^2.0.5",
|
|
17
|
-
"framer-motion": "^11.3.
|
|
17
|
+
"framer-motion": "^11.3.19",
|
|
18
18
|
"html-react-parser": "^5.1.12",
|
|
19
19
|
"lodash": "^4.17.21",
|
|
20
20
|
"lodash.debounce": "^4.0.8",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"react-dom": "^17.0.1"
|
|
59
59
|
},
|
|
60
60
|
"name": "@visns-studio/visns-components",
|
|
61
|
-
"version": "4.5.
|
|
61
|
+
"version": "4.5.8",
|
|
62
62
|
"description": "Various packages to assist in the development of our Custom Applications.",
|
|
63
63
|
"main": "index.js",
|
|
64
64
|
"scripts": {
|