@nyris/nyris-webapp 0.3.57 → 0.3.59

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.
Files changed (94) hide show
  1. package/build/asset-manifest.json +15 -16
  2. package/build/index.html +1 -1
  3. package/build/js/settings.example.js +1 -0
  4. package/build/static/css/main.cb6e2cfd.css +4 -0
  5. package/build/static/css/main.cb6e2cfd.css.map +1 -0
  6. package/build/static/js/main.a1e24447.js +3 -0
  7. package/build/static/js/{main.5143aa56.js.LICENSE.txt → main.a1e24447.js.LICENSE.txt} +55 -0
  8. package/build/static/js/main.a1e24447.js.map +1 -0
  9. package/build/static/media/camera_simple.bff4194954bbb5f4bc33bd99014a93e8.svg +3 -0
  10. package/build/static/media/collpase.50dae91fff891c46b10dfc281344d0ef.svg +6 -0
  11. package/build/static/media/crop.0676ebbbdc1375ed67e32bba890ce941.svg +3 -0
  12. package/build/static/media/{download.8007f7c72e2080a9ffa96fa63d480dcf.svg → download.a8452bc23334e9f8e53fe1225742d216.svg} +1 -1
  13. package/build/static/media/gallery.15d1f3308921480a8c9d96d9a77c9966.svg +3 -0
  14. package/build/static/media/{logout.b544fcd2969edf431a1e998333119834.svg → logout.bab56bd407f25eb34d6eff401a436ce1.svg} +1 -1
  15. package/build/static/media/next-arrow.b13263d05d107ceb5e99bc4fabb41279.svg +3 -0
  16. package/build/static/media/plus.329672cb2feb55345490589e91481b88.svg +3 -0
  17. package/package.json +8 -5
  18. package/public/index.html +0 -3
  19. package/public/js/settings.example.js +1 -0
  20. package/src/Router.tsx +2 -2
  21. package/src/Store/Store.ts +2 -0
  22. package/src/Store/requestStore.ts +70 -0
  23. package/src/Store/resultStore.ts +25 -0
  24. package/src/Store/search/Search.ts +2 -33
  25. package/src/Store/search/search.initialState.ts +1 -4
  26. package/src/Store/search/types.ts +0 -5
  27. package/src/common/assets/icons/arrow_enter.svg +3 -0
  28. package/src/common/assets/icons/camera_simple.svg +3 -0
  29. package/src/common/assets/icons/collpase.svg +6 -0
  30. package/src/common/assets/icons/crop.svg +3 -0
  31. package/src/common/assets/icons/download.svg +1 -1
  32. package/src/common/assets/icons/gallery.svg +3 -0
  33. package/src/common/assets/icons/logout.svg +1 -1
  34. package/src/common/assets/icons/next-arrow.svg +3 -0
  35. package/src/common/assets/icons/plus.svg +3 -0
  36. package/src/components/CadenasWebViewer.tsx +1 -1
  37. package/src/components/DragDropFile.tsx +17 -77
  38. package/src/components/Experience-visual-search/ExperienceVisualSearch.tsx +47 -71
  39. package/src/components/Feedback.tsx +23 -9
  40. package/src/components/GoBackButton.tsx +15 -18
  41. package/src/components/HeaderMobile.tsx +342 -246
  42. package/src/components/ImageCaptureHelpModal.tsx +63 -65
  43. package/src/components/ImagePreview.tsx +564 -0
  44. package/src/components/Inquiry/InquiryBanner.tsx +1 -1
  45. package/src/components/Inquiry/InquiryModal.tsx +4 -7
  46. package/src/components/Layout.tsx +9 -18
  47. package/src/components/MobileLayout.tsx +51 -0
  48. package/src/components/MobilePostFilter.tsx +9 -3
  49. package/src/components/PanelResult/PostFilterAlgolia.tsx +4 -32
  50. package/src/components/PanelResult/expandable-panel.tsx +3 -16
  51. package/src/components/PanelResult/virtual-state-results.ts +17 -22
  52. package/src/components/ProductDetailView.tsx +1 -1
  53. package/src/components/SidePanel.tsx +7 -97
  54. package/src/components/UploadDisclaimer.tsx +85 -0
  55. package/src/components/appMobile.scss +2 -2
  56. package/src/components/common.scss +57 -27
  57. package/src/components/drawer/cameraCustom.tsx +389 -231
  58. package/src/components/icon-label/icon-label.tsx +1 -1
  59. package/src/components/input/inputSearch.tsx +197 -338
  60. package/src/components/pre-filter/index.tsx +70 -72
  61. package/src/components/results/ItemResult.tsx +34 -17
  62. package/src/components/rfq/RfqBanner.tsx +1 -4
  63. package/src/components/rfq/RfqModal.tsx +10 -10
  64. package/src/hooks/useFilteredRegions.ts +1 -1
  65. package/src/hooks/useImageSearch.ts +189 -0
  66. package/src/hooks/useSearchOrRedirect.ts +84 -0
  67. package/src/index.css +4 -0
  68. package/src/page/landingPage/Home.tsx +49 -0
  69. package/src/page/landingPage/{AppMD.tsx → HomeDesktop.tsx} +7 -34
  70. package/src/page/landingPage/{AppMobile.tsx → HomeMobile.tsx} +8 -37
  71. package/src/page/landingPage/common.scss +9 -1
  72. package/src/page/result/index.tsx +118 -232
  73. package/src/services/Feedback.ts +4 -5
  74. package/src/services/image.ts +19 -0
  75. package/src/types.ts +9 -7
  76. package/src/utils.ts +44 -0
  77. package/tailwind.config.js +54 -0
  78. package/build/static/css/main.67965609.css +0 -2
  79. package/build/static/css/main.67965609.css.map +0 -1
  80. package/build/static/js/main.5143aa56.js +0 -3
  81. package/build/static/js/main.5143aa56.js.map +0 -1
  82. package/build/static/media/arrow_down.f417689ce292978a8292a7f00407fdd5.svg +0 -3
  83. package/build/static/media/arrow_left.73d03a534eaf9b99ab196e0fb67da602.svg +0 -3
  84. package/build/static/media/arrow_right.59a4594a3a1657037537dbae1eee0251.svg +0 -3
  85. package/build/static/media/arrow_up.85dbe70bc51ec32c8894a06499330f14.svg +0 -3
  86. package/build/static/media/home.9ffb65a9c0be8fc5a502ba05cf5f719c.svg +0 -3
  87. package/build/static/media/icon_camera_mobile.6772053c4dfef487255649d2a05cc9d4.svg +0 -3
  88. package/build/static/media/reverse_camera.cee0200b151941cc83c182167a85d667.svg +0 -5
  89. package/src/App.tsx +0 -18
  90. package/src/components/AppMobile.tsx +0 -117
  91. package/src/components/FooterMobile.tsx +0 -230
  92. package/src/components/ImagePreviewMobile.tsx +0 -237
  93. /package/build/static/media/{add.2b72cedb98c4c89c954266d2356c166c.svg → add-rounded.2b72cedb98c4c89c954266d2356c166c.svg} +0 -0
  94. /package/src/common/assets/icons/{add.svg → add-rounded.svg} +0 -0
@@ -1,21 +1,13 @@
1
- import React, {
2
- memo,
3
- useCallback,
4
- useEffect,
5
- useMemo,
6
- useRef,
7
- useState,
8
- } from 'react';
1
+ import { memo, useEffect, useMemo, useRef, useState } from 'react';
9
2
  import { useHistory } from 'react-router-dom';
10
3
  import ArrowLeftIcon from '@material-ui/icons/ArrowLeft';
11
4
  import ArrowRightIcon from '@material-ui/icons/ArrowRight';
12
5
 
13
- import { RectCoords } from '@nyris/nyris-api';
14
6
  import { CurrentRefinements } from 'components/current-refinements/current-refinements';
15
7
  import FooterResult from 'components/FooterResult';
16
8
  import CustomSearchBox from 'components/input/inputSearch';
17
9
  import ProductList from 'components/ProductList';
18
- import { debounce, isEmpty } from 'lodash';
10
+ import { isEmpty } from 'lodash';
19
11
  import {
20
12
  Configure,
21
13
  connectStateResults,
@@ -23,33 +15,19 @@ import {
23
15
  Pagination,
24
16
  } from 'react-instantsearch-dom';
25
17
  import { useMediaQuery } from 'react-responsive';
26
- import { feedbackRegionEpic, feedbackSuccessEpic } from 'services/Feedback';
27
- import { createImage, find, findRegions } from 'services/image';
18
+ import { feedbackSuccessEpic } from 'services/Feedback';
28
19
  import {
29
20
  loadingActionResults,
30
21
  onToggleModalItemDetail,
31
- selectionChanged,
32
- setImageSearchInput,
33
- setRegions,
34
- setRequestImage,
35
- setSearchResults,
36
- setSelectedRegion,
37
22
  setShowFeedback,
38
- updateResultChangePosition,
39
23
  updateStatusLoading,
40
- setFirstSearchResults,
41
- setFirstSearchImage,
42
- setFirstSearchPrefilters,
43
- setFirstSearchThumbSearchInput,
44
24
  } from 'Store/search/Search';
45
25
  import { useAppDispatch, useAppSelector } from 'Store/Store';
46
26
  import { showHits } from '../../constants';
47
- import { DEFAULT_REGION } from '../../constants';
48
27
  import { useTranslation } from 'react-i18next';
49
28
  import RfqModal from 'components/rfq/RfqModal';
50
29
  import SidePanel from 'components/SidePanel';
51
- import useFilteredRegions from 'hooks/useFilteredRegions';
52
- import ImagePreviewMobile from 'components/ImagePreviewMobile';
30
+ import ImagePreview from 'components/ImagePreview';
53
31
  import RfqBanner from 'components/rfq/RfqBanner';
54
32
  import InquiryBanner from 'components/Inquiry/InquiryBanner';
55
33
  import { useQuery } from 'hooks/useQuery';
@@ -57,6 +35,8 @@ import { ReactComponent as PoweredByNyrisImage } from 'common/assets/images/powe
57
35
  import Feedback from 'components/Feedback';
58
36
  import { SelectedPostFilter } from 'components/SelectedPostFilter';
59
37
  import { GoBack } from '../../components/GoBackButton';
38
+ import { useImageSearch } from 'hooks/useImageSearch';
39
+ import useRequestStore from 'Store/requestStore';
60
40
 
61
41
  interface Props {
62
42
  allSearchResults: any;
@@ -71,11 +51,9 @@ function ResultComponent(props: Props) {
71
51
  const { allSearchResults } = props;
72
52
  const {
73
53
  requestImage,
74
- regions,
75
54
  selectedRegion,
76
55
  preFilter,
77
56
  loadingSearchAlgolia,
78
- imageThumbSearchInput,
79
57
  results,
80
58
  showFeedback,
81
59
  firstSearchResults,
@@ -84,18 +62,16 @@ function ResultComponent(props: Props) {
84
62
  } = search;
85
63
 
86
64
  const isMobile = useMediaQuery({ query: '(max-width: 776px)' });
87
- const [imageSelection, setImageSelection] = useState<any>(null);
88
65
  const executeScroll = () => refBoxResult.current.scrollIntoView('-100px');
89
66
  const [filterString, setFilterString] = useState<string>();
90
67
  const { t } = useTranslation();
91
- const [showAdjustInfo, setAdjustInfo] = useState(false);
92
- const [showAdjustInfoBasedOnConfidence, setShowAdjustInfoBasedOnConfidence] =
93
- useState(false);
68
+ const [showAdjustInfo] = useState(false);
69
+
94
70
  const [rfqStatus, setRfqStatus] = useState<'inactive' | 'loading' | 'sent'>(
95
71
  'inactive',
96
72
  );
97
73
  const [isRfqModalOpen, setIsRfqModalOpen] = useState(false);
98
- const imageUploadRef = useRef(null);
74
+ // const imageUploadRef = useRef(null);
99
75
  const rfqRef = useRef<any>(null);
100
76
 
101
77
  const [feedbackStatus, setFeedbackStatus] = useState<
@@ -109,24 +85,35 @@ function ResultComponent(props: Props) {
109
85
  const isPostFilterEnabled = settings.postFilterOption;
110
86
  const history = useHistory();
111
87
 
112
- useEffect(() => {
113
- if (
114
- !loadingSearchAlgolia &&
115
- (imageThumbSearchInput.includes('blob:') ||
116
- imageThumbSearchInput.includes('data:')) &&
117
- imageUploadRef.current !== imageThumbSearchInput
118
- ) {
119
- setAdjustInfo(true);
120
- const timeout = setTimeout(() => {
121
- setAdjustInfo(false);
122
- }, 2000);
123
- imageUploadRef.current = imageThumbSearchInput;
124
- return () => {
125
- clearTimeout(timeout);
126
- setAdjustInfo(false);
127
- };
128
- }
129
- }, [imageThumbSearchInput, loadingSearchAlgolia]);
88
+ const { singleImageSearch, multiImageSearch } = useImageSearch();
89
+
90
+ const { resetRegions, imageRegions, requestImages } = useRequestStore(
91
+ state => ({
92
+ requestImages: state.requestImages,
93
+ updateRegion: state.updateRegion,
94
+ resetRegions: state.resetRegions,
95
+ imageRegions: state.regions,
96
+ }),
97
+ );
98
+
99
+ // useEffect(() => {
100
+ // if (
101
+ // !loadingSearchAlgolia &&
102
+ // (imageThumbSearchInput.includes('blob:') ||
103
+ // imageThumbSearchInput.includes('data:')) &&
104
+ // imageUploadRef.current !== imageThumbSearchInput
105
+ // ) {
106
+ // setAdjustInfo(true);
107
+ // const timeout = setTimeout(() => {
108
+ // setAdjustInfo(false);
109
+ // }, 2000);
110
+ // imageUploadRef.current = imageThumbSearchInput;
111
+ // return () => {
112
+ // clearTimeout(timeout);
113
+ // setAdjustInfo(false);
114
+ // };
115
+ // }
116
+ // }, [imageThumbSearchInput, loadingSearchAlgolia]);
130
117
 
131
118
  useEffect(() => {
132
119
  if (loadingSearchAlgolia) {
@@ -137,7 +124,6 @@ function ResultComponent(props: Props) {
137
124
 
138
125
  useEffect(() => {
139
126
  if (selectedRegion) {
140
- setImageSelection(selectedRegion);
141
127
  setRfqStatus('inactive');
142
128
  setFeedbackStatus('hidden');
143
129
  }
@@ -147,66 +133,11 @@ function ResultComponent(props: Props) {
147
133
  if (requestImage) {
148
134
  setFeedbackStatus('hidden');
149
135
  executeScroll();
150
- setImageSelection(DEFAULT_REGION);
136
+ resetRegions();
151
137
  }
138
+ // eslint-disable-next-line react-hooks/exhaustive-deps
152
139
  }, [requestImage]);
153
140
 
154
- const findImageByApiNyris = useCallback(
155
- async (canvas: any, r?: RectCoords) => {
156
- const preFilterValues = [
157
- {
158
- key: settings.visualSearchFilterKey,
159
- values: Object.keys(preFilter)
160
- },
161
- ];
162
- dispatch(loadingActionResults());
163
-
164
- return find({
165
- image: canvas,
166
- settings,
167
- region: r,
168
- filters: !isEmpty(preFilter) ? preFilterValues : undefined,
169
- })
170
- .then((res: any) => {
171
- dispatch(updateStatusLoading(false));
172
- return {
173
- ...res,
174
- };
175
- })
176
- .catch((e: any) => {
177
- dispatch(updateStatusLoading(false));
178
- console.log('error call api change selection find image', e);
179
- });
180
- },
181
- [settings, dispatch, preFilter],
182
- );
183
-
184
- // TODO: Search offers for image:
185
- // eslint-disable-next-line react-hooks/exhaustive-deps
186
- const findItemsInSelection = useCallback(
187
- debounce(async (r: RectCoords) => {
188
- if (!requestImage) {
189
- return;
190
- }
191
- dispatch(updateStatusLoading(true));
192
- const { canvas }: any = requestImage;
193
- findImageByApiNyris(canvas, r).then((res: any) => {
194
- dispatch(updateResultChangePosition(res));
195
- const highConfidence = res.results.find(
196
- (data: { score: number }) => data.score >= 0.65,
197
- );
198
- if (!highConfidence) {
199
- setShowAdjustInfoBasedOnConfidence(true);
200
- }
201
- setTimeout(() => {
202
- setShowAdjustInfoBasedOnConfidence(false);
203
- }, 2000);
204
- });
205
- return;
206
- }, 250),
207
- [requestImage, findImageByApiNyris],
208
- );
209
-
210
141
  // TODO: Handler like dislike
211
142
  const sendFeedBackAction = async (type: string) => {
212
143
  feedbackSuccessEpic(stateGlobal, type === 'like');
@@ -221,46 +152,10 @@ function ResultComponent(props: Props) {
221
152
  dispatch(onToggleModalItemDetail(false));
222
153
  }
223
154
  dispatch(loadingActionResults());
224
- dispatch(setImageSearchInput(url));
225
- let image = await createImage(url);
226
- dispatch(setRequestImage(image));
227
-
228
- let searchRegion: RectCoords | undefined = undefined;
229
-
230
- try {
231
- if (settings.regions) {
232
- let res = await findRegions(image, settings);
233
- searchRegion = res.selectedRegion;
234
- dispatch(setRegions(res.regions));
235
- dispatch(setSelectedRegion(searchRegion));
236
- }
237
- } catch (error) {
238
- } finally {
239
- const preFilterValues = [
240
- {
241
- key: settings.visualSearchFilterKey,
242
- values: Object.keys(preFilter),
243
- },
244
- ];
245
- find({
246
- image,
247
- settings,
248
- region: searchRegion,
249
- filters: !isEmpty(preFilter) ? preFilterValues : undefined,
250
- }).then((res: any) => {
251
- if (!firstSearchResults) {
252
- dispatch(setFirstSearchResults(res));
253
- dispatch(setFirstSearchImage(image));
254
- dispatch(setFirstSearchPrefilters(preFilter));
255
- if (!isMobile) {
256
- dispatch(setFirstSearchThumbSearchInput(url))
257
- }
258
- }
259
- dispatch(setSearchResults(res));
260
- dispatch(updateStatusLoading(false));
261
- return;
262
- });
263
- }
155
+
156
+ singleImageSearch({ image: url, settings, showFeedback: true }).then(() => {
157
+ dispatch(updateStatusLoading(false));
158
+ });
264
159
  };
265
160
  const nonEmptyFilter: any[] = !requestImage
266
161
  ? []
@@ -275,7 +170,7 @@ function ResultComponent(props: Props) {
275
170
 
276
171
  useEffect(() => {
277
172
  document.title = 'Search results';
278
- setFeedbackStatus('hidden');
173
+ // setFeedbackStatus('hidden');
279
174
 
280
175
  if (requestImage || isEmpty(searchQuery)) return;
281
176
  const preFilterValues = Object.keys(preFilter) as string[];
@@ -290,15 +185,29 @@ function ResultComponent(props: Props) {
290
185
  }, [preFilter, requestImage, searchQuery, settings.alogoliaFilterField]);
291
186
 
292
187
  useEffect(() => {
293
- if (!requestImage || !isAlgoliaEnabled) {
188
+ if (requestImages.length === 0 || !isAlgoliaEnabled) {
294
189
  return;
295
190
  }
296
191
  dispatch(updateStatusLoading(true));
297
- const { canvas }: any = requestImage;
298
- findImageByApiNyris(canvas).then((res: any) => {
299
- // setPreFilter(keyFilter);
300
- dispatch(updateResultChangePosition(res));
301
- });
192
+ dispatch(loadingActionResults());
193
+
194
+ if (requestImages.length === 1) {
195
+ singleImageSearch({
196
+ image: requestImages[0],
197
+ settings,
198
+ imageRegion: imageRegions[0],
199
+ }).then(res => {
200
+ dispatch(updateStatusLoading(false));
201
+ });
202
+ } else {
203
+ multiImageSearch({
204
+ images: requestImages,
205
+ settings,
206
+ regions: imageRegions,
207
+ }).then(res => {
208
+ dispatch(updateStatusLoading(false));
209
+ });
210
+ }
302
211
 
303
212
  return () => {};
304
213
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -335,17 +244,6 @@ function ResultComponent(props: Props) {
335
244
  }, [history.location]);
336
245
 
337
246
  // eslint-disable-next-line react-hooks/exhaustive-deps
338
- const debouncedOnImageSelectionChange = useCallback(
339
- debounce((r: RectCoords) => {
340
- setImageSelection(r);
341
- feedbackRegionEpic(stateGlobal, r);
342
- dispatch(selectionChanged(r));
343
- findItemsInSelection(r);
344
- }, 50),
345
- [findItemsInSelection, stateGlobal.search],
346
- );
347
-
348
- const filteredRegions = useFilteredRegions(regions, imageSelection);
349
247
 
350
248
  const showPostFilter = useMemo(() => {
351
249
  return (
@@ -364,17 +262,15 @@ function ResultComponent(props: Props) {
364
262
  return;
365
263
 
366
264
  const handleScroll = () => {
367
- setTimeout(() => {
368
- setFeedbackStatus(s => (s === 'submitted' ? 'submitted' : 'visible'));
369
- dispatch(setShowFeedback(false));
370
- }, 100);
265
+ setFeedbackStatus(s => (s === 'submitted' ? 'submitted' : 'visible'));
266
+ dispatch(setShowFeedback(false));
371
267
  };
372
268
 
373
269
  setTimeout(() => {
374
270
  window.removeEventListener('scroll', handleScroll, { capture: true });
375
271
  setFeedbackStatus(s => (s === 'submitted' ? 'submitted' : 'visible'));
376
272
  dispatch(setShowFeedback(false));
377
- }, 4000);
273
+ }, 3000);
378
274
 
379
275
  window.addEventListener('scroll', handleScroll, {
380
276
  capture: true,
@@ -408,8 +304,6 @@ function ResultComponent(props: Props) {
408
304
  <>
409
305
  {isRfqModalOpen && (
410
306
  <RfqModal
411
- requestImage={requestImage}
412
- selectedRegion={selectedRegion}
413
307
  setIsRfqModalOpen={setIsRfqModalOpen}
414
308
  isRfqModalOpen={isRfqModalOpen}
415
309
  setRfqStatus={setRfqStatus}
@@ -435,17 +329,8 @@ function ResultComponent(props: Props) {
435
329
  >
436
330
  {!isMobile && showSidePanel && (
437
331
  <SidePanel
438
- setImageSelection={setImageSelection}
439
332
  allSearchResults={props.allSearchResults}
440
- debouncedOnImageSelectionChange={
441
- debouncedOnImageSelectionChange
442
- }
443
- filteredRegions={filteredRegions}
444
- imageSelection={imageSelection}
445
333
  showAdjustInfo={showAdjustInfo}
446
- showAdjustInfoBasedOnConfidence={
447
- showAdjustInfoBasedOnConfidence
448
- }
449
334
  showPostFilter={showPostFilter}
450
335
  disjunctiveFacets={props.allSearchResults.disjunctiveFacets}
451
336
  />
@@ -456,38 +341,57 @@ function ResultComponent(props: Props) {
456
341
  settings.preview && 'ml-auto mr-auto'
457
342
  } ${isMobile && 'col-right-result-mobile'}`}
458
343
  style={{
459
- paddingTop: isMobile ? '8px' : '40px',
344
+ paddingTop: isMobile ? '0px' : '40px',
460
345
  overflow: !isMobile ? 'auto' : '',
461
346
  display: 'flex',
462
347
  flexDirection: 'column',
348
+ overflowX: 'hidden',
349
+ position: 'relative',
463
350
  }}
464
351
  >
465
- {!isMobile && firstSearchResults && requestImage?.canvas !== firstSearchImage && !fetchingResults ? (
352
+ {showFeedbackSuccess && (
353
+ <div className={'feedback-floating'}>
354
+ <div className="feedback-section">
355
+ <div className="feedback-success">
356
+ Thanks for your feedback!
357
+ </div>
358
+ </div>
359
+ </div>
360
+ )}
361
+ {feedbackStatus === 'visible' && !showFeedbackSuccess && (
362
+ <div className={'feedback-floating'}>
363
+ <div className="feedback-section">
364
+ <Feedback
365
+ submitFeedback={submitFeedback}
366
+ onFeedbackClose={() => {
367
+ setFeedbackStatus('submitted');
368
+ dispatch(setShowFeedback(false));
369
+ }}
370
+ />
371
+ </div>
372
+ </div>
373
+ )}
374
+
375
+ {!isMobile &&
376
+ firstSearchResults &&
377
+ requestImages[0] !== firstSearchImage &&
378
+ !fetchingResults ? (
466
379
  <GoBack />
467
380
  ) : (
468
381
  ''
469
382
  )}
470
-
383
+
471
384
  {!isMobile && settings.algolia.enabled && (
472
385
  <div className="wrap-box-refinements">
473
386
  <CurrentRefinements statusSwitchButton={true} />
474
387
  </div>
475
388
  )}
476
389
 
477
- {isMobile && settings.preview && requestImage && (
478
- <ImagePreviewMobile
479
- requestImage={requestImage}
480
- imageSelection={imageSelection}
481
- debouncedOnImageSelectionChange={
482
- debouncedOnImageSelectionChange
483
- }
484
- filteredRegions={filteredRegions}
485
- showAdjustInfoBasedOnConfidence={
486
- showAdjustInfoBasedOnConfidence
487
- }
488
- showAdjustInfo={showAdjustInfo}
489
- />
490
- )}
390
+ <div className="flex flex-col h-fit desktop:hidden">
391
+ {settings.preview && requestImages.length > 0 && (
392
+ <ImagePreview showAdjustInfo={false} />
393
+ )}
394
+ </div>
491
395
 
492
396
  <div
493
397
  style={{
@@ -496,15 +400,19 @@ function ResultComponent(props: Props) {
496
400
  flexGrow: 1,
497
401
  backgroundColor: '#FAFAFA',
498
402
  }}
403
+ className="mt-4 desktop:mt-0"
499
404
  >
500
- {isMobile && firstSearchResults && requestImage?.canvas !== firstSearchImage && !fetchingResults ? (
405
+ {isMobile &&
406
+ firstSearchResults &&
407
+ requestImages[0] !== firstSearchImage &&
408
+ !fetchingResults ? (
501
409
  <div className="go-back-mobile-container">
502
410
  <GoBack />
503
411
  </div>
504
412
  ) : (
505
413
  ''
506
414
  )}
507
-
415
+
508
416
  <div
509
417
  className={'box-item-result ml-auto mr-auto'}
510
418
  style={{
@@ -527,34 +435,12 @@ function ResultComponent(props: Props) {
527
435
  requestImage={requestImage}
528
436
  searchQuery={searchQuery}
529
437
  />
530
- <div
438
+ {/* <div
531
439
  className="box-item-result ml-auto mr-auto"
532
440
  style={{ position: 'absolute' }}
533
441
  >
534
- {showFeedbackSuccess && (
535
- <div className={'feedback-floating'}>
536
- <div className="feedback-section">
537
- <div className="feedback-success">
538
- Thanks for your feedback!
539
- </div>
540
- </div>
541
- </div>
542
- )}
543
- {feedbackStatus === 'visible' &&
544
- !showFeedbackSuccess && (
545
- <div className={'feedback-floating'}>
546
- <div className="feedback-section">
547
- <Feedback
548
- submitFeedback={submitFeedback}
549
- onFeedbackClose={() => {
550
- setFeedbackStatus('submitted');
551
- dispatch(setShowFeedback(false));
552
- }}
553
- />
554
- </div>
555
- </div>
556
- )}
557
- </div>
442
+
443
+ </div> */}
558
444
  </div>
559
445
  </div>
560
446
  <div
@@ -596,7 +482,7 @@ function ResultComponent(props: Props) {
596
482
  marginTop: !isAlgoliaEnabled ? '24px' : '',
597
483
  }}
598
484
  >
599
- {requestImage &&
485
+ {requestImages.length > 0 &&
600
486
  !loadingSearchAlgolia &&
601
487
  !props.isSearchStalled &&
602
488
  settings.rfq &&
@@ -605,8 +491,8 @@ function ResultComponent(props: Props) {
605
491
  rfqRef={rfqRef}
606
492
  rfqStatus={rfqStatus}
607
493
  setIsRfqModalOpen={setIsRfqModalOpen}
608
- requestImage={requestImage}
609
- selectedRegion={selectedRegion}
494
+ requestImage={requestImages[0]}
495
+ selectedRegion={imageRegions[0]}
610
496
  />
611
497
  )}
612
498
  {!loadingSearchAlgolia &&
@@ -615,8 +501,8 @@ function ResultComponent(props: Props) {
615
501
  settings.support.enabled &&
616
502
  (searchQuery || requestImage) && (
617
503
  <InquiryBanner
618
- requestImage={requestImage}
619
- selectedRegion={selectedRegion}
504
+ requestImage={requestImages[0]}
505
+ selectedRegion={imageRegions[0]}
620
506
  query={searchQuery}
621
507
  />
622
508
  )}
@@ -10,10 +10,9 @@ export const feedbackSuccessEpic = async (
10
10
  success: boolean,
11
11
  ) => {
12
12
  const { search, settings } = state;
13
- const sessionId = search.sessionId;
14
- const requestId = search.requestId || search.sessionId;
13
+ const requestId = search.requestId;
15
14
 
16
- return await sendFeedbackByApi(settings, sessionId, requestId, {
15
+ return await sendFeedbackByApi(settings, undefined, requestId, {
17
16
  event: 'feedback',
18
17
  data: { success },
19
18
  });
@@ -64,9 +63,9 @@ export const sendFeedbackByApi = async (
64
63
  payload: FeedbackEventPayload,
65
64
  ) => {
66
65
  const api = new NyrisAPI(settings);
67
- if (sessionId && requestId) {
66
+ if (requestId) {
68
67
  try {
69
- await api.sendFeedback(sessionId, requestId, payload).then(res => {});
68
+ await api.sendFeedback({ sessionId, requestId, payload }).then(res => {});
70
69
  } catch (error) {
71
70
  console.log('error sendFeedbackByApi', error);
72
71
  }
@@ -70,3 +70,22 @@ export const find = ({
70
70
  }
71
71
  return nyrisApi.find(options, image, filters);
72
72
  };
73
+
74
+ export const findMulti = ({
75
+ images,
76
+ settings,
77
+ regions,
78
+ filters,
79
+ text,
80
+ }: {
81
+ images?: HTMLCanvasElement[];
82
+ settings: NyrisAPISettings;
83
+ regions?: RectCoords[];
84
+ filters?: Filter[];
85
+ text?: string;
86
+ }) => {
87
+ const nyrisApi = new NyrisAPI(settings);
88
+ let options: ImageSearchOptions = text ? { text } : {};
89
+
90
+ return nyrisApi.findMulti(options, images, regions, filters);
91
+ };
package/src/types.ts CHANGED
@@ -53,16 +53,20 @@ export interface AppSettings extends NyrisAPISettings {
53
53
  appTitle?: string;
54
54
  auth0: Auth0Settings;
55
55
  brandName?: string;
56
- isBrandNameTitleVisible?: boolean;
57
56
  cadenas?: Cadenas;
57
+ clarityId?: string;
58
58
  CTAButtonText?: string;
59
- secondaryCTAButtonText?: string;
59
+ experienceVisualSearch?: boolean;
60
+ experienceVisualSearchImages?: string[];
60
61
  field: Field;
61
62
  headerText?: string;
62
63
  instantRedirectPatterns: string[];
64
+ isBrandNameTitleVisible?: boolean;
63
65
  itemIdLabel?: string;
64
66
  language?: string;
67
+ multiImageSearch?: boolean;
65
68
  noImageUrl?: string;
69
+ noSimilarSearch?: boolean;
66
70
  postFilterOption?: boolean;
67
71
  preFilterOption?: boolean;
68
72
  preFilterTitle?: string;
@@ -70,20 +74,18 @@ export interface AppSettings extends NyrisAPISettings {
70
74
  refinements?: any;
71
75
  regions: boolean;
72
76
  rfq?: Rfq;
77
+ secondaryCTAButtonText?: string;
73
78
  shareOption?: boolean;
79
+ shouldUseUserMetadata?: boolean;
74
80
  showFeedback?: boolean;
75
81
  showFeedbackAndShare?: boolean;
76
82
  showGroup?: boolean;
77
83
  showPoweredByNyris?: boolean;
78
- support?: Support;
79
84
  simpleCardView?: boolean;
85
+ support?: Support;
80
86
  theme: SearchSuiteSettings;
81
87
  visualSearchFilterKey?: string;
82
88
  warehouseVariant?: boolean;
83
- shouldUseUserMetadata?: boolean;
84
- experienceVisualSearch?: boolean;
85
- experienceVisualSearchImages?: string[];
86
- clarityId?: string,
87
89
  }
88
90
 
89
91
  export interface SearchSuiteSettings {