@nyris/nyris-webapp 0.3.87 → 0.3.89
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/build/asset-manifest.json +6 -6
- package/build/index.html +1 -1
- package/build/js/settings.example.js +1 -0
- package/build/static/css/main.ba1c7479.css +4 -0
- package/build/static/css/main.ba1c7479.css.map +1 -0
- package/build/static/js/main.ca8b95bc.js +3 -0
- package/build/static/js/{main.029b0c0c.js.map → main.ca8b95bc.js.map} +1 -1
- package/package.json +3 -3
- package/public/js/settings.example.js +1 -0
- package/src/components/Carousel/ImagePreviewCarousel.tsx +1 -1
- package/src/components/CustomCameraDrawer.tsx +73 -3
- package/src/components/DragDropFile.tsx +121 -46
- package/src/components/Header.tsx +17 -12
- package/src/components/Hint.tsx +98 -0
- package/src/components/ImagePreview.tsx +79 -10
- package/src/components/Inquiry/InquiryModal.tsx +40 -9
- package/src/components/PreFilter/PreFilter.tsx +14 -0
- package/src/components/Product/Product.tsx +3 -3
- package/src/components/Product/ProductDetailView.tsx +2 -4
- package/src/components/Product/ProductList.tsx +0 -5
- package/src/components/SidePanel.tsx +77 -84
- package/src/components/TextSearch.tsx +161 -9
- package/src/layouts/AppLayout.tsx +14 -10
- package/src/pages/Home.tsx +20 -2
- package/src/pages/Result.tsx +84 -65
- package/src/stores/request/requestStore.ts +5 -1
- package/src/stores/request/specifications/specifications.initialState.ts +9 -0
- package/src/stores/request/specifications/specifications.slice.ts +15 -0
- package/src/stores/types.ts +16 -0
- package/src/styles/common.scss +15 -0
- package/src/styles/product.scss +13 -1
- package/src/translations.ts +27 -0
- package/src/types.ts +1 -0
- package/build/static/css/main.a0a44a64.css +0 -4
- package/build/static/css/main.a0a44a64.css.map +0 -1
- package/build/static/js/main.029b0c0c.js +0 -3
- /package/build/static/js/{main.029b0c0c.js.LICENSE.txt → main.ca8b95bc.js.LICENSE.txt} +0 -0
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nyris/nyris-webapp",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.89",
|
|
4
4
|
"dependencies": {
|
|
5
5
|
"@auth0/auth0-react": "^2.2.4",
|
|
6
6
|
"@emailjs/browser": "^4.3.3",
|
|
7
|
-
"@nyris/nyris-api": "^0.3.
|
|
8
|
-
"@nyris/nyris-react-components": "^0.3.
|
|
7
|
+
"@nyris/nyris-api": "^0.3.89",
|
|
8
|
+
"@nyris/nyris-react-components": "^0.3.89",
|
|
9
9
|
"@radix-ui/react-accordion": "^1.2.2",
|
|
10
10
|
"@radix-ui/react-dialog": "^1.1.4",
|
|
11
11
|
"@radix-ui/react-popover": "^1.1.4",
|
|
@@ -84,7 +84,7 @@ export const ImagePreviewCarousel = (props: Props) => {
|
|
|
84
84
|
}}
|
|
85
85
|
options={mainOptions}
|
|
86
86
|
ref={mainRef}
|
|
87
|
-
style={{ maxWidth: '100%', height: isMobile ? '80%' : '' }}
|
|
87
|
+
style={{ maxWidth: '100%', height: isMobile ? '80%' : 'calc(100% - 48px);' }}
|
|
88
88
|
>
|
|
89
89
|
{renderSlides()}
|
|
90
90
|
</Splide>
|
|
@@ -18,6 +18,9 @@ import {
|
|
|
18
18
|
} from './Drawer/Drawer';
|
|
19
19
|
import { useCadSearch } from 'hooks/useCadSearch';
|
|
20
20
|
import { isCadFile } from '@nyris/nyris-api';
|
|
21
|
+
import { clone } from 'lodash';
|
|
22
|
+
import { getFilters } from '../services/filter';
|
|
23
|
+
import { useTranslation } from 'react-i18next';
|
|
21
24
|
|
|
22
25
|
interface Props {
|
|
23
26
|
show: boolean;
|
|
@@ -35,18 +38,42 @@ function CustomCamera(props: Props) {
|
|
|
35
38
|
const location = useLocation();
|
|
36
39
|
const { singleImageSearch } = useImageSearch();
|
|
37
40
|
const { cadSearch } = useCadSearch();
|
|
41
|
+
const { t } = useTranslation();
|
|
38
42
|
|
|
39
43
|
const requestImages = useRequestStore(state => state.requestImages);
|
|
40
|
-
|
|
44
|
+
const specifications = useRequestStore(state => state.specifications);
|
|
45
|
+
const setSpecifications = useRequestStore(state => state.setSpecifications);
|
|
46
|
+
const setRequestImages = useRequestStore(state => state.setRequestImages);
|
|
47
|
+
const setNameplateNotificationText = useRequestStore(state => state.setNameplateNotificationText);
|
|
48
|
+
const setAlgoliaFilter = useRequestStore(state => state.setAlgoliaFilter);
|
|
49
|
+
const setPreFilter = useRequestStore(state => state.setPreFilter);
|
|
50
|
+
const setShowLoading = useRequestStore(state => state.setShowLoading);
|
|
51
|
+
const setNameplateImage = useRequestStore(state => state.setNameplateImage);
|
|
52
|
+
const setShowNotMatchedError = useRequestStore(state => state.setShowNotMatchedError);
|
|
41
53
|
const [capturedImages, setCapturedImages] = useState<HTMLCanvasElement[]>([]);
|
|
42
54
|
const [currentIndex, setCurrentIndex] = useState(0);
|
|
43
55
|
const [imageCaptureHelpModal, setImageCaptureHelpModal] = useState(false);
|
|
56
|
+
const [resultFilter, setResultFilter] = useState<any>([]);
|
|
44
57
|
|
|
45
58
|
const videoConstraints = {
|
|
46
59
|
width: 1080,
|
|
47
60
|
aspectRatio: 1.11111,
|
|
48
61
|
};
|
|
49
62
|
|
|
63
|
+
const getPreFilters = async () => {
|
|
64
|
+
getFilters(1000, settings)
|
|
65
|
+
.then(res => {
|
|
66
|
+
setResultFilter(res);
|
|
67
|
+
})
|
|
68
|
+
.catch((e: any) => {
|
|
69
|
+
console.log('err getDataFilterDesktop', e);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
getPreFilters()
|
|
75
|
+
}, []);
|
|
76
|
+
|
|
50
77
|
const handlerFindImage = async (image: any) => {
|
|
51
78
|
if (location.pathname !== '/result') {
|
|
52
79
|
navigate('/result');
|
|
@@ -65,8 +92,51 @@ function CustomCamera(props: Props) {
|
|
|
65
92
|
settings,
|
|
66
93
|
newSearch,
|
|
67
94
|
showFeedback: true,
|
|
68
|
-
}).then(() => {
|
|
69
|
-
|
|
95
|
+
}).then((singleImageResp) => {
|
|
96
|
+
const specificationPrefilter = singleImageResp.image_analysis?.specification?.prefilter_value || null;
|
|
97
|
+
const hasPrefilter = resultFilter.filter((filter: any) => filter.values.includes(specificationPrefilter));
|
|
98
|
+
if (specificationPrefilter) {
|
|
99
|
+
setRequestImages([]);
|
|
100
|
+
setShowNotMatchedError(false);
|
|
101
|
+
if (hasPrefilter.length) {
|
|
102
|
+
setSpecifications(clone(singleImageResp.image_analysis.specification));
|
|
103
|
+
setNameplateImage(image);
|
|
104
|
+
setPreFilter({[singleImageResp.image_analysis?.specification?.prefilter_value]: true});
|
|
105
|
+
setAlgoliaFilter(`${settings.alogoliaFilterField}:'${singleImageResp.image_analysis?.specification?.prefilter_value}'`);
|
|
106
|
+
|
|
107
|
+
setShowLoading(false);
|
|
108
|
+
handleClose();
|
|
109
|
+
|
|
110
|
+
setNameplateNotificationText(t('We have successfully defined the search criteria', { prefilter_value: specificationPrefilter, preFilterTitle: window.settings.preFilterTitle?.toLocaleLowerCase() }));
|
|
111
|
+
setTimeout(() => {
|
|
112
|
+
setNameplateNotificationText('');
|
|
113
|
+
}, 5000);
|
|
114
|
+
}
|
|
115
|
+
if (!hasPrefilter.length && window.settings.preFilterOption) {
|
|
116
|
+
setSpecifications(clone({...singleImageResp.image_analysis.specification, prefilter_value: '', specificationPrefilter}));
|
|
117
|
+
setPreFilter({});
|
|
118
|
+
setAlgoliaFilter('');
|
|
119
|
+
setShowLoading(false);
|
|
120
|
+
handleClose();
|
|
121
|
+
setShowNotMatchedError(true);
|
|
122
|
+
setTimeout(() => {
|
|
123
|
+
setNameplateNotificationText(t('Extracted details from the nameplate could not be matched', { preFilterTitle: window.settings.preFilterTitle?.toLocaleLowerCase() }));
|
|
124
|
+
}, 1000);
|
|
125
|
+
setTimeout(() => {
|
|
126
|
+
setNameplateNotificationText('');
|
|
127
|
+
}, 6000);
|
|
128
|
+
}
|
|
129
|
+
} else {
|
|
130
|
+
if (specifications?.is_nameplate) {
|
|
131
|
+
setSpecifications({...specifications, prefilter_value: '', specificationPrefilter: ''});
|
|
132
|
+
} else {
|
|
133
|
+
setSpecifications({...specifications, is_nameplate: false});
|
|
134
|
+
}
|
|
135
|
+
setShowLoading(false);
|
|
136
|
+
handleClose();
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
|
|
70
140
|
};
|
|
71
141
|
|
|
72
142
|
const handleClose = () => {
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import { memo } from 'react';
|
|
1
|
+
import { memo, useEffect, useState } from 'react';
|
|
2
2
|
import { twMerge } from 'tailwind-merge';
|
|
3
3
|
import { useTranslation } from 'react-i18next';
|
|
4
4
|
|
|
5
|
-
import { Icon } from '@nyris/nyris-react-components';
|
|
6
|
-
|
|
7
5
|
import Loading from './Loading';
|
|
8
6
|
import { useImageSearch } from 'hooks/useImageSearch';
|
|
9
7
|
import useDragAndDrop from 'hooks/useDragAndDrop';
|
|
10
8
|
import { useNavigate } from 'react-router';
|
|
11
9
|
import { useCadSearch } from 'hooks/useCadSearch';
|
|
12
10
|
import { isCadFile } from '@nyris/nyris-api';
|
|
11
|
+
import Hint from './Hint';
|
|
12
|
+
import { clone } from 'lodash';
|
|
13
|
+
import useRequestStore from '../stores/request/requestStore';
|
|
14
|
+
import { getFilters } from '../services/filter';
|
|
13
15
|
|
|
14
16
|
interface Props {
|
|
15
17
|
onChangeLoading?: any;
|
|
@@ -24,8 +26,33 @@ function DragDropFile(props: Props) {
|
|
|
24
26
|
const { singleImageSearch } = useImageSearch();
|
|
25
27
|
const { cadSearch } = useCadSearch();
|
|
26
28
|
|
|
29
|
+
const [resultFilter, setResultFilter] = useState<any>([]);
|
|
30
|
+
|
|
31
|
+
const specifications = useRequestStore(state => state.specifications);
|
|
32
|
+
const setRequestImages = useRequestStore(state => state.setRequestImages);
|
|
33
|
+
const setSpecifications = useRequestStore(state => state.setSpecifications);
|
|
34
|
+
const setNameplateNotificationText = useRequestStore(state => state.setNameplateNotificationText);
|
|
35
|
+
const setShowNotMatchedError = useRequestStore(state => state.setShowNotMatchedError);
|
|
36
|
+
const setAlgoliaFilter = useRequestStore(state => state.setAlgoliaFilter);
|
|
37
|
+
const setPreFilter = useRequestStore(state => state.setPreFilter);
|
|
38
|
+
const setShowLoading = useRequestStore(state => state.setShowLoading);
|
|
39
|
+
const setNameplateImage = useRequestStore(state => state.setNameplateImage);
|
|
40
|
+
|
|
41
|
+
const getPreFilters = async () => {
|
|
42
|
+
getFilters(1000, window.settings)
|
|
43
|
+
.then(res => {
|
|
44
|
+
setResultFilter(res);
|
|
45
|
+
})
|
|
46
|
+
.catch((e: any) => {
|
|
47
|
+
console.log('err getDataFilterDesktop', e);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
getPreFilters()
|
|
53
|
+
}, []);
|
|
54
|
+
|
|
27
55
|
const handleUpload = (file: File) => {
|
|
28
|
-
navigate('/result');
|
|
29
56
|
|
|
30
57
|
if (isCadFile(file)) {
|
|
31
58
|
cadSearch({
|
|
@@ -37,11 +64,58 @@ function DragDropFile(props: Props) {
|
|
|
37
64
|
return;
|
|
38
65
|
}
|
|
39
66
|
|
|
67
|
+
setShowLoading(true);
|
|
68
|
+
|
|
40
69
|
singleImageSearch({
|
|
41
70
|
image: file,
|
|
42
71
|
settings: window.settings,
|
|
43
72
|
showFeedback: true,
|
|
44
|
-
}).then(() => {
|
|
73
|
+
}).then((singleImageResp) => {
|
|
74
|
+
const specificationPrefilter = singleImageResp.image_analysis?.specification?.prefilter_value || null;
|
|
75
|
+
const hasPrefilter = resultFilter.filter((filter: any) => filter.values.includes(specificationPrefilter));
|
|
76
|
+
if (specificationPrefilter) {
|
|
77
|
+
setRequestImages([]);
|
|
78
|
+
setShowNotMatchedError(false);
|
|
79
|
+
if (hasPrefilter.length) {
|
|
80
|
+
setSpecifications(clone(singleImageResp.image_analysis.specification));
|
|
81
|
+
setNameplateImage(file);
|
|
82
|
+
setPreFilter({[singleImageResp.image_analysis?.specification?.prefilter_value]: true});
|
|
83
|
+
setAlgoliaFilter(`${window.settings.alogoliaFilterField}:'${singleImageResp.image_analysis?.specification?.prefilter_value}'`);
|
|
84
|
+
|
|
85
|
+
setShowLoading(false);
|
|
86
|
+
navigate('/result');
|
|
87
|
+
|
|
88
|
+
setTimeout(() => {
|
|
89
|
+
setNameplateNotificationText(t('We have successfully defined the search criteria', { prefilter_value: specificationPrefilter, preFilterTitle: window.settings.preFilterTitle?.toLocaleLowerCase() }));
|
|
90
|
+
}, 1000);
|
|
91
|
+
setTimeout(() => {
|
|
92
|
+
setNameplateNotificationText('');
|
|
93
|
+
}, 6000);
|
|
94
|
+
}
|
|
95
|
+
if (!hasPrefilter.length && window.settings.preFilterOption) {
|
|
96
|
+
setSpecifications(clone({...singleImageResp.image_analysis.specification, prefilter_value: '', specificationPrefilter}));
|
|
97
|
+
navigate('/result');
|
|
98
|
+
setPreFilter({});
|
|
99
|
+
setAlgoliaFilter('');
|
|
100
|
+
setShowLoading(false);
|
|
101
|
+
setShowNotMatchedError(true);
|
|
102
|
+
setTimeout(() => {
|
|
103
|
+
setNameplateNotificationText(t('Extracted details from the nameplate could not be matched', { preFilterTitle: window.settings.preFilterTitle?.toLocaleLowerCase() }));
|
|
104
|
+
}, 1000);
|
|
105
|
+
setTimeout(() => {
|
|
106
|
+
setNameplateNotificationText('');
|
|
107
|
+
}, 6000);
|
|
108
|
+
}
|
|
109
|
+
} else {
|
|
110
|
+
if (specifications?.is_nameplate) {
|
|
111
|
+
setSpecifications({...specifications, prefilter_value: '', specificationPrefilter: ''});
|
|
112
|
+
} else {
|
|
113
|
+
setSpecifications({...specifications, is_nameplate: false});
|
|
114
|
+
}
|
|
115
|
+
setShowLoading(false);
|
|
116
|
+
navigate('/result');
|
|
117
|
+
}
|
|
118
|
+
});
|
|
45
119
|
};
|
|
46
120
|
|
|
47
121
|
const { isDragging, dragProps } = useDragAndDrop({
|
|
@@ -49,52 +123,53 @@ function DragDropFile(props: Props) {
|
|
|
49
123
|
});
|
|
50
124
|
|
|
51
125
|
return (
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
{isLoading && <Loading />}
|
|
59
|
-
|
|
60
|
-
<div
|
|
61
|
-
className={'relative flex flex-col items-center justify-center w-full'}
|
|
62
|
-
{...dragProps}
|
|
126
|
+
<>
|
|
127
|
+
<label
|
|
128
|
+
htmlFor="select_file"
|
|
129
|
+
className={
|
|
130
|
+
'flex flex-col items-center justify-center mt-8 bg-[#fafafa] drag-n-drop-label'
|
|
131
|
+
}
|
|
63
132
|
>
|
|
133
|
+
{isLoading && <Loading />}
|
|
134
|
+
|
|
64
135
|
<div
|
|
65
|
-
className={
|
|
66
|
-
|
|
67
|
-
'text-[#cacad1] hover:text-primary',
|
|
68
|
-
'border-2 border-dashed border-transparent hover:border-[#e0e0e0]',
|
|
69
|
-
isDragging && 'text-primary border-[#e0e0e0]',
|
|
70
|
-
])}
|
|
136
|
+
className={'relative flex flex-col items-center justify-center w-full'}
|
|
137
|
+
{...dragProps}
|
|
71
138
|
>
|
|
72
|
-
<div
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
139
|
+
<div
|
|
140
|
+
className={twMerge([
|
|
141
|
+
'drag-n-drop-inner',
|
|
142
|
+
'flex flex-col items-center w-full cursor-pointer pb-4 pt-4 rounded-[12px]',
|
|
143
|
+
'text-[#cacad1] hover:text-primary',
|
|
144
|
+
'border-2 border-dashed border-transparent hover:border-[#e0e0e0]',
|
|
145
|
+
isDragging && 'text-primary border-[#e0e0e0]',
|
|
146
|
+
])}
|
|
147
|
+
>
|
|
148
|
+
<div className="" style={{ fontSize: 14 }}>
|
|
149
|
+
<span className="font-bold text-sm pr-1">{t('Drag and drop')}</span>
|
|
150
|
+
{t('an image here')}
|
|
151
|
+
</div>
|
|
152
|
+
<Hint />
|
|
153
|
+
<input
|
|
154
|
+
onChange={e => {
|
|
155
|
+
e.stopPropagation();
|
|
156
|
+
if (e.target.files && e.target.files[0]) {
|
|
157
|
+
handleUpload(e.target.files[0]);
|
|
158
|
+
e.target.value = '';
|
|
159
|
+
}
|
|
160
|
+
}}
|
|
161
|
+
style={{}}
|
|
162
|
+
type="file"
|
|
163
|
+
name="file"
|
|
164
|
+
id="select_file"
|
|
165
|
+
className="absolute z-[-1] opacity-0"
|
|
166
|
+
placeholder="Choose photo"
|
|
167
|
+
accept={'.stp,.step,.stl,.obj,.glb,.gltf,.heic,.heif,.pdf,image/*'}
|
|
168
|
+
/>
|
|
78
169
|
</div>
|
|
79
|
-
<input
|
|
80
|
-
onChange={e => {
|
|
81
|
-
e.stopPropagation();
|
|
82
|
-
if (e.target.files && e.target.files[0]) {
|
|
83
|
-
handleUpload(e.target.files[0]);
|
|
84
|
-
e.target.value = '';
|
|
85
|
-
}
|
|
86
|
-
}}
|
|
87
|
-
style={{}}
|
|
88
|
-
type="file"
|
|
89
|
-
name="file"
|
|
90
|
-
id="select_file"
|
|
91
|
-
className="absolute z-[-1] opacity-0"
|
|
92
|
-
placeholder="Choose photo"
|
|
93
|
-
accept={'.stp,.step,.stl,.obj,.glb,.gltf,.heic,.heif,.pdf,image/*'}
|
|
94
|
-
/>
|
|
95
170
|
</div>
|
|
96
|
-
</
|
|
97
|
-
|
|
171
|
+
</label>
|
|
172
|
+
</>
|
|
98
173
|
);
|
|
99
174
|
}
|
|
100
175
|
|
|
@@ -19,6 +19,7 @@ function Header() {
|
|
|
19
19
|
|
|
20
20
|
const reset = useRequestStore(state => state.reset);
|
|
21
21
|
const resetResultStore = useResultStore(state => state.reset);
|
|
22
|
+
const setSpecifications = useRequestStore(state => state.setSpecifications);
|
|
22
23
|
|
|
23
24
|
const showSearchBar = location?.pathname === '/result';
|
|
24
25
|
|
|
@@ -42,8 +43,9 @@ function Header() {
|
|
|
42
43
|
>
|
|
43
44
|
<div
|
|
44
45
|
className={twMerge([
|
|
46
|
+
'w-full',
|
|
45
47
|
'flex',
|
|
46
|
-
'justify-
|
|
48
|
+
'justify-center',
|
|
47
49
|
'items-center',
|
|
48
50
|
'relative',
|
|
49
51
|
'h-full',
|
|
@@ -51,10 +53,11 @@ function Header() {
|
|
|
51
53
|
>
|
|
52
54
|
<NavLink
|
|
53
55
|
to="/"
|
|
54
|
-
style={{ lineHeight: 0 }}
|
|
56
|
+
style={{ lineHeight: 0, position: 'absolute', left: 0 }}
|
|
55
57
|
onClick={() => {
|
|
56
58
|
reset();
|
|
57
59
|
resetResultStore();
|
|
60
|
+
setSpecifications(null);
|
|
58
61
|
}}
|
|
59
62
|
>
|
|
60
63
|
<img
|
|
@@ -68,16 +71,18 @@ function Header() {
|
|
|
68
71
|
/>
|
|
69
72
|
</NavLink>
|
|
70
73
|
|
|
71
|
-
<div
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
74
|
+
<div>
|
|
75
|
+
<div
|
|
76
|
+
className={twMerge(['hidden', showSearchBar && 'desktop:block'])}
|
|
77
|
+
style={{
|
|
78
|
+
// position: 'relative',
|
|
79
|
+
// left: '50%',
|
|
80
|
+
// top: '50%',
|
|
81
|
+
// transform: 'translate(-50%, -50%)',
|
|
82
|
+
}}
|
|
83
|
+
>
|
|
84
|
+
<TextSearch />
|
|
85
|
+
</div>
|
|
81
86
|
</div>
|
|
82
87
|
|
|
83
88
|
{auth0.enabled && isAuthenticated && (
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Icon } from '@nyris/nyris-react-components';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
|
|
5
|
+
const Hint = () => {
|
|
6
|
+
const { t } = useTranslation();
|
|
7
|
+
return (
|
|
8
|
+
<div
|
|
9
|
+
style={{
|
|
10
|
+
width: 'max-content',
|
|
11
|
+
minWidth: 240,
|
|
12
|
+
display: 'flex',
|
|
13
|
+
flexDirection: 'row',
|
|
14
|
+
justifyContent: 'space-between',
|
|
15
|
+
marginTop: 16,
|
|
16
|
+
fontSize: 9,
|
|
17
|
+
fontWeight: 700,
|
|
18
|
+
whiteSpace: 'nowrap',
|
|
19
|
+
gap: 16,
|
|
20
|
+
}}
|
|
21
|
+
>
|
|
22
|
+
<div
|
|
23
|
+
style={{
|
|
24
|
+
display: 'flex',
|
|
25
|
+
flexDirection: 'column',
|
|
26
|
+
alignItems: 'center',
|
|
27
|
+
flex: 1,
|
|
28
|
+
}}
|
|
29
|
+
>
|
|
30
|
+
<Icon
|
|
31
|
+
name="typeplate"
|
|
32
|
+
width={24}
|
|
33
|
+
height={24}
|
|
34
|
+
style={{
|
|
35
|
+
marginBottom: 8,
|
|
36
|
+
}}
|
|
37
|
+
/>
|
|
38
|
+
{t('Type plates')}
|
|
39
|
+
</div>
|
|
40
|
+
<div
|
|
41
|
+
style={{
|
|
42
|
+
display: 'flex',
|
|
43
|
+
flexDirection: 'column',
|
|
44
|
+
alignItems: 'center',
|
|
45
|
+
flex: 1,
|
|
46
|
+
}}
|
|
47
|
+
>
|
|
48
|
+
<Icon
|
|
49
|
+
name="part"
|
|
50
|
+
width={24}
|
|
51
|
+
height={24}
|
|
52
|
+
style={{
|
|
53
|
+
marginBottom: 8,
|
|
54
|
+
}}
|
|
55
|
+
/>
|
|
56
|
+
{t('Parts')}
|
|
57
|
+
</div>
|
|
58
|
+
<div
|
|
59
|
+
style={{
|
|
60
|
+
display: 'flex',
|
|
61
|
+
flexDirection: 'column',
|
|
62
|
+
alignItems: 'center',
|
|
63
|
+
flex: 1,
|
|
64
|
+
}}
|
|
65
|
+
>
|
|
66
|
+
<Icon
|
|
67
|
+
name="label"
|
|
68
|
+
width={24}
|
|
69
|
+
height={24}
|
|
70
|
+
style={{
|
|
71
|
+
marginBottom: 8,
|
|
72
|
+
}}
|
|
73
|
+
/>
|
|
74
|
+
{t('Labels')}
|
|
75
|
+
</div>
|
|
76
|
+
<div
|
|
77
|
+
style={{
|
|
78
|
+
display: 'flex',
|
|
79
|
+
flexDirection: 'column',
|
|
80
|
+
alignItems: 'center',
|
|
81
|
+
flex: 1,
|
|
82
|
+
}}
|
|
83
|
+
>
|
|
84
|
+
<Icon
|
|
85
|
+
name="barcode"
|
|
86
|
+
width={24}
|
|
87
|
+
height={24}
|
|
88
|
+
style={{
|
|
89
|
+
marginBottom: 8,
|
|
90
|
+
}}
|
|
91
|
+
/>
|
|
92
|
+
{t('Barcodes')}
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export default Hint;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {useCallback, useEffect, useRef, useState} from 'react';
|
|
2
2
|
|
|
3
|
-
import { debounce
|
|
3
|
+
import {clone, debounce} from 'lodash';
|
|
4
4
|
import { twMerge } from 'tailwind-merge';
|
|
5
5
|
import { useNavigate } from 'react-router';
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
@@ -12,6 +12,7 @@ import { DEFAULT_REGION } from '../constants';
|
|
|
12
12
|
import { useImageSearch } from 'hooks/useImageSearch';
|
|
13
13
|
import useRequestStore from 'stores/request/requestStore';
|
|
14
14
|
import useResultStore from 'stores/result/resultStore';
|
|
15
|
+
import { getFilters } from '../services/filter';
|
|
15
16
|
|
|
16
17
|
function ImagePreviewComponent({
|
|
17
18
|
showAdjustInfo = false,
|
|
@@ -23,6 +24,7 @@ function ImagePreviewComponent({
|
|
|
23
24
|
}) {
|
|
24
25
|
const [showAdjustInfoBasedOnConfidence, setShowAdjustInfoBasedOnConfidence] =
|
|
25
26
|
useState(false);
|
|
27
|
+
const [resultFilter, setResultFilter] = useState<any>([]);
|
|
26
28
|
|
|
27
29
|
const { t } = useTranslation();
|
|
28
30
|
const navigate = useNavigate();
|
|
@@ -30,11 +32,19 @@ function ImagePreviewComponent({
|
|
|
30
32
|
const isMultiImageSearchEnabled = settings.multiImageSearch;
|
|
31
33
|
|
|
32
34
|
const requestImages = useRequestStore(state => state.requestImages);
|
|
35
|
+
const specifications = useRequestStore(state => state.specifications);
|
|
33
36
|
const resetRegions = useRequestStore(state => state.resetRegions);
|
|
34
37
|
const setRequestImages = useRequestStore(state => state.setRequestImages);
|
|
35
38
|
const regions = useRequestStore(state => state.regions);
|
|
36
39
|
const updateRegion = useRequestStore(state => state.updateRegion);
|
|
37
40
|
const resetRequestStore = useRequestStore(state => state.reset);
|
|
41
|
+
const setSpecifications = useRequestStore(state => state.setSpecifications);
|
|
42
|
+
const setShowLoading = useRequestStore(state => state.setShowLoading);
|
|
43
|
+
const setNameplateNotificationText = useRequestStore(state => state.setNameplateNotificationText);
|
|
44
|
+
const setAlgoliaFilter = useRequestStore(state => state.setAlgoliaFilter);
|
|
45
|
+
const setPreFilter = useRequestStore(state => state.setPreFilter);
|
|
46
|
+
const setNameplateImage = useRequestStore(state => state.setNameplateImage);
|
|
47
|
+
const setShowNotMatchedError = useRequestStore(state => state.setShowNotMatchedError);
|
|
38
48
|
|
|
39
49
|
const detectedRegions = useResultStore(state => state.detectedRegions);
|
|
40
50
|
const resetResultStore = useResultStore(state => state.reset);
|
|
@@ -48,6 +58,20 @@ function ImagePreviewComponent({
|
|
|
48
58
|
|
|
49
59
|
const previewWrapperRef = useRef<any>(null);
|
|
50
60
|
|
|
61
|
+
const getPreFilters = async () => {
|
|
62
|
+
getFilters(1000, settings)
|
|
63
|
+
.then(res => {
|
|
64
|
+
setResultFilter(res);
|
|
65
|
+
})
|
|
66
|
+
.catch((e: any) => {
|
|
67
|
+
console.log('err getDataFilterDesktop', e);
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
getPreFilters()
|
|
73
|
+
}, []);
|
|
74
|
+
|
|
51
75
|
const onImageRemove = () => {
|
|
52
76
|
resetRegions();
|
|
53
77
|
setRequestImages([]);
|
|
@@ -55,6 +79,7 @@ function ImagePreviewComponent({
|
|
|
55
79
|
navigate('/');
|
|
56
80
|
resetResultStore();
|
|
57
81
|
resetRequestStore();
|
|
82
|
+
setSpecifications(null);
|
|
58
83
|
};
|
|
59
84
|
|
|
60
85
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
@@ -69,15 +94,59 @@ function ImagePreviewComponent({
|
|
|
69
94
|
showFeedback: true,
|
|
70
95
|
compress: false,
|
|
71
96
|
}).then((res: any) => {
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
|
|
97
|
+
const specificationPrefilter = res.image_analysis?.specification?.prefilter_value || null;
|
|
98
|
+
const hasPrefilter = resultFilter.filter((filter: any) => filter.values.includes(specificationPrefilter));
|
|
99
|
+
if (specificationPrefilter) {
|
|
100
|
+
setRequestImages([]);
|
|
101
|
+
setShowNotMatchedError(false);
|
|
102
|
+
if (hasPrefilter.length) {
|
|
103
|
+
setSpecifications(clone(res.image_analysis.specification));
|
|
104
|
+
setNameplateImage(image);
|
|
105
|
+
setPreFilter({[res.image_analysis?.specification?.prefilter_value]: true});
|
|
106
|
+
setAlgoliaFilter(`${settings.alogoliaFilterField}:'${res.image_analysis?.specification?.prefilter_value}'`);
|
|
107
|
+
|
|
108
|
+
setShowLoading(false);
|
|
109
|
+
navigate('/result');
|
|
110
|
+
|
|
111
|
+
setTimeout(() => {
|
|
112
|
+
setNameplateNotificationText(t('We have successfully defined the search criteria', {
|
|
113
|
+
prefilter_value: specificationPrefilter,
|
|
114
|
+
preFilterTitle: window.settings.preFilterTitle?.toLocaleLowerCase()
|
|
115
|
+
}));
|
|
116
|
+
}, 1000);
|
|
117
|
+
setTimeout(() => {
|
|
118
|
+
setNameplateNotificationText('');
|
|
119
|
+
}, 6000);
|
|
120
|
+
}
|
|
121
|
+
if (!hasPrefilter.length && window.settings.preFilterOption) {
|
|
122
|
+
setSpecifications(clone({...res.image_analysis.specification, prefilter_value: '', specificationPrefilter}));
|
|
123
|
+
setPreFilter({});
|
|
124
|
+
setAlgoliaFilter('');
|
|
125
|
+
setShowLoading(false);
|
|
126
|
+
setShowNotMatchedError(true);
|
|
127
|
+
setTimeout(() => {
|
|
128
|
+
setNameplateNotificationText(t('Extracted details from the nameplate could not be matched', { preFilterTitle: window.settings.preFilterTitle?.toLocaleLowerCase() }));
|
|
129
|
+
}, 1000);
|
|
130
|
+
setTimeout(() => {
|
|
131
|
+
setNameplateNotificationText('');
|
|
132
|
+
}, 6000);
|
|
133
|
+
}
|
|
134
|
+
} else {
|
|
135
|
+
if (specifications?.is_nameplate) {
|
|
136
|
+
setSpecifications({...specifications, prefilter_value: '', specificationPrefilter: ''});
|
|
137
|
+
} else {
|
|
138
|
+
setSpecifications({...specifications, is_nameplate: false});
|
|
139
|
+
}
|
|
140
|
+
const highConfidence = res.results.find(
|
|
141
|
+
(data: { score: number }) => data.score >= 0.65,
|
|
142
|
+
);
|
|
143
|
+
if (!highConfidence) {
|
|
144
|
+
setShowAdjustInfoBasedOnConfidence(true);
|
|
145
|
+
}
|
|
146
|
+
setTimeout(() => {
|
|
147
|
+
setShowAdjustInfoBasedOnConfidence(false);
|
|
148
|
+
}, 2000);
|
|
77
149
|
}
|
|
78
|
-
setTimeout(() => {
|
|
79
|
-
setShowAdjustInfoBasedOnConfidence(false);
|
|
80
|
-
}, 2000);
|
|
81
150
|
});
|
|
82
151
|
return;
|
|
83
152
|
}, 1500),
|