@nyris/nyris-webapp 0.3.4 → 0.3.5

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.
@@ -10,15 +10,6 @@ import React, { useEffect, useState } from "react";
10
10
  import IconWhatsApp from "common/assets/icons/Icon_whatsapp.png";
11
11
  import IconEmail from "common/assets/icons/icon_email.png";
12
12
  import IconWeChat from "common/assets/icons/Icon_wechat.png";
13
- // import FilterComponent from "components/FilterComponent";
14
- // import {
15
- // dataFieldFive,
16
- // dataFieldFour,
17
- // dataFieldOne,
18
- // dataFieldSix,
19
- // dataFieldThree,
20
- // dataFieldTow,
21
- // } from "./MockData";
22
13
  import ItemResult from "components/results/ItemResult";
23
14
  import { useAppDispatch, useAppSelector } from "Store/Store";
24
15
  import { debounce } from "lodash";
@@ -33,9 +24,8 @@ import { RectCoords } from "@nyris/nyris-api";
33
24
  import {
34
25
  setSearchResults,
35
26
  loadingActionResults,
36
- searchFileImageNonRegion,
37
27
  selectionChanged,
38
- updateResultChangePosition,
28
+ updateResultChangePosition, setRegions, setSelectedRegion,
39
29
  } from "Store/Search";
40
30
  import { showFeedback, showResults } from "Store/Nyris";
41
31
  import algoliasearch from "algoliasearch/lite";
@@ -46,37 +36,35 @@ import {
46
36
  Configure,
47
37
  } from "react-instantsearch-dom";
48
38
  import CustomSearchBox from "components/input/inputSearch";
49
- import { feedbackClickEpic } from "services/Feedback";
39
+ import {feedbackClickEpic, feedbackSuccessEpic, feedbackTextSearchEpic} from "services/Feedback";
50
40
  import {
51
- searchImageByPosition,
52
- serviceImage,
53
- serviceImageNonRegion,
41
+ createImage, findByImage, findRegions,
54
42
  } from "services/image";
55
- import NyrisAPI from "@nyris/nyris-api";
56
43
  import LoadingScreenCustom from "components/LoadingScreen";
57
44
  import { Preview } from "@nyris/nyris-react-components";
45
+ import {AlgoliaResult, AlgoliaSettings} from "../../types";
58
46
 
59
47
  interface Props {}
60
48
 
49
+ const defaultSelection = {x1: 0.1, x2: 0.9, y1: 0.1, y2: 0.9};
61
50
  function ResultComponent(props: Props) {
62
51
  const dispatch = useAppDispatch();
63
- const StateGlobal = useAppSelector((state) => state);
52
+ const stateGlobal = useAppSelector((state) => state);
64
53
  const [showColLeft, setToggleShowColLeft] = useState<boolean>(false);
65
54
  const [showImageCanvas, setShowImageCanvas] = useState<boolean>(true);
66
55
  const [isOpenModalImage, setOpenModalImage] = useState<boolean>(false);
67
56
  const [numberResult, setNumberResult] = useState<number>(0);
68
57
  const [isOpenModalShare, setOpenModalShare] = useState<boolean>(false);
69
- const { search, settings }: any = StateGlobal;
70
- const { results, requestImage, regions, selectedRegion }: any = search;
58
+ const { search, settings } = stateGlobal;
59
+ const { results, requestImage, regions, selectedRegion } = search;
71
60
  const { valueTextSearch } = search;
72
61
  const [dataResult, setDataResult] = useState<any[]>([]);
73
62
  const [dataImageModal, setDataImageModal] = useState<any>();
74
63
  const [searchStateInput, setSearchStateInput] = useState<any>({});
75
- const apiNyris = new NyrisAPI(settings);
76
64
  const [isLoading, setLoading] = useState<any>(false);
77
- const { apiKeyAlgolia, appIdAlgolia, indexNameAlgolia } = settings;
78
- const searchClient = algoliasearch(appIdAlgolia, apiKeyAlgolia);
79
- const index = searchClient.initIndex(indexNameAlgolia);
65
+ const { apiKey, appId, indexName } = settings.algolia as AlgoliaSettings;
66
+ const searchClient = algoliasearch(appId, apiKey);
67
+ const index = searchClient.initIndex(indexName);
80
68
 
81
69
  useEffect(() => {
82
70
  if (!valueTextSearch) {
@@ -127,102 +115,64 @@ function ResultComponent(props: Props) {
127
115
  const handlerRectCoords = debounce((value: any) => {
128
116
  dispatch(selectionChanged(value));
129
117
  setLoading(true);
130
- return onSearchOffersForImage(value);
118
+ return findItemsInSelection(value);
131
119
  }, 500);
132
120
 
133
121
  // TODO: Search offers for image:
134
- const onSearchOffersForImage = (r: RectCoords) => {
122
+ const findItemsInSelection = (r: RectCoords) => {
135
123
  if (!requestImage) {
136
124
  return;
137
125
  }
138
126
  const { canvas }: any = requestImage;
139
- if (settings.regions) {
140
- searchImageByPosition(canvas, StateGlobal, r).then((res: any) => {
141
- const payload = {
142
- ...res,
143
- requestImage: requestImage,
144
- };
145
- dispatch(updateResultChangePosition(payload));
146
- setLoading(false);
147
- return dispatch(showFeedback());
148
- });
149
- } else {
150
- serviceImageNonRegion(canvas, StateGlobal, null).then((res: any) => {
151
- const payload = {
152
- ...res,
153
- requestImage: requestImage,
154
- };
155
- dispatch(updateResultChangePosition(payload));
156
- return dispatch(showFeedback());
157
- });
158
- }
127
+ findByImage(canvas, stateGlobal.settings, r).then((res) => {
128
+ const payload = {
129
+ ...res,
130
+ };
131
+ dispatch(updateResultChangePosition(payload));
132
+ setLoading(false);
133
+ return dispatch(showFeedback());
134
+ });
159
135
  };
160
136
 
161
137
  // TODO: Search text
162
138
  const searchTextByApiAndFilter = async (searchState: any) => {
163
139
  try {
164
140
  if (searchState?.query !== "") {
165
- const data = await index.search(searchState.query, {});
166
- const productIds = data.hits.map((hit: any) => hit.sku);
167
- const eventData = {
168
- query: data.query,
169
- page: data.page,
170
- product_ids: productIds,
171
- };
172
- const textSearchEvent: any = { event: "text-search", data: eventData };
173
- await apiNyris.sendFeedback(
174
- search?.sessionId,
175
- search?.requestId,
176
- textSearchEvent
177
- );
141
+ const data = await index.search<AlgoliaResult>(searchState.query, {});
142
+ const productIds = data.hits.map((hit) => hit.sku);
143
+ await feedbackTextSearchEpic(stateGlobal, data.query, data.page, productIds);
178
144
  }
179
- } catch (error: any) {
145
+ } catch (error) {
180
146
  console.log("searchTextByApi", error);
181
147
  return;
182
148
  }
183
149
  };
184
150
 
185
- // TODO: Handler like dislike
186
- const sendFeedBackAction = async (type: string) => {
187
- try {
188
- const action = type === "like" ? true : false;
189
- const payload: any = {
190
- event: "feedback",
191
- data: {
192
- success: action,
193
- },
194
- };
195
- await apiNyris.sendFeedback(
196
- search?.sessionId,
197
- search?.requestId,
198
- payload
199
- );
200
- } catch (error) {}
201
- };
151
+ const sendFeedBackAction = async (type: string) =>
152
+ feedbackSuccessEpic(stateGlobal, type === "like");
202
153
 
203
154
  // Search image with url or file
204
- const getUrlToCanvasFile = (url: string, position?: number) => {
155
+ const getUrlToCanvasFile = async (url: string, position?: number) => {
205
156
  dispatch(showResults());
206
157
  dispatch(loadingActionResults());
158
+ let image = await createImage(url);
207
159
  if (position) {
208
- feedbackClickEpic(StateGlobal, position);
160
+ feedbackClickEpic(stateGlobal, position);
209
161
  return;
210
162
  }
163
+ let searchRegion : RectCoords | undefined = undefined;
211
164
  if (settings.regions) {
212
- serviceImage(url, settings).then((res ) => {
213
- console.log("res", res)
214
- dispatch(setSearchResults(res));
215
- setLoading(false);
216
- return dispatch(showFeedback());
217
- });
218
-
219
- return;
220
- } else {
221
- serviceImageNonRegion(url, StateGlobal, undefined).then((res) => {
222
- dispatch(searchFileImageNonRegion(res));
223
- });
224
- return;
165
+ let res = await findRegions(image, settings);
166
+ searchRegion = res.selectedRegion;
167
+ dispatch(setRegions(res.regions));
168
+ dispatch(setSelectedRegion(searchRegion));
225
169
  }
170
+
171
+ findByImage(image, settings, searchRegion).then((res ) => {
172
+ dispatch(setSearchResults(res));
173
+ setLoading(false);
174
+ return dispatch(showFeedback());
175
+ });
226
176
  };
227
177
 
228
178
  // Todo: item result.
@@ -248,12 +198,12 @@ function ResultComponent(props: Props) {
248
198
  );
249
199
  };
250
200
 
251
- const nonEmptyFilter: any[] = !search?.requestImage
201
+ const nonEmptyFilter: any[] = !requestImage
252
202
  ? []
253
203
  : ["sku:DOES_NOT_EXIST<score=1>"];
254
204
  const filterSkus: any = search?.results
255
- ? search?.results.map(
256
- (f: any) => `sku:'${f.sku}'<score=${Math.round(100 * f.score)}>`
205
+ ? search?.results.slice().reverse().map(
206
+ (f: any, i: number) => `sku:'${f.sku}'<score=${i}>`
257
207
  )
258
208
  : "";
259
209
  const filtersString = [...nonEmptyFilter, ...filterSkus].join(" OR ");
@@ -268,10 +218,10 @@ function ResultComponent(props: Props) {
268
218
  </Box>
269
219
  )}
270
220
  <InstantSearch
271
- indexName={indexNameAlgolia}
221
+ indexName={indexName}
272
222
  searchClient={searchClient}
273
223
  searchState={searchStateInput}
274
- onSearchStateChange={(state: any) => {
224
+ onSearchStateChange={(state) => {
275
225
  setSearchStateInput(state);
276
226
  searchTextByApiAndFilter(state);
277
227
  }}
@@ -314,7 +264,7 @@ function ResultComponent(props: Props) {
314
264
  return;
315
265
  }}
316
266
  image={requestImage?.canvas}
317
- selection={selectedRegion}
267
+ selection={selectedRegion|| defaultSelection}
318
268
  regions={regions}
319
269
  maxWidth={400}
320
270
  maxHeight={500}
@@ -1,65 +1,64 @@
1
- import NyrisAPI from "@nyris/nyris-api";
1
+ import NyrisAPI, {FeedbackEventPayload, NyrisAPISettings, RectCoords} from "@nyris/nyris-api";
2
+ import {RootState} from "../Store/Store";
2
3
 
3
- export const feedbackSuccessEpic = async (state: any, success: boolean) => {
4
+ export const feedbackSuccessEpic = async (state: RootState, success: boolean) => {
4
5
  const { search, settings } = state;
5
- try {
6
- const api = new NyrisAPI(settings);
7
- const sessionId = search.sessionId || search.requestId;
8
- return await api.sendFeedback(sessionId, search.requestId, {
9
- event: "feedback",
10
- data: { success },
11
- });
12
- } catch (error) {
13
- console.log("error feedbackSuccessEpic", error);
14
- }
6
+ return await sendFeedbackByApi(settings, search.sessionId, search.requestId, {
7
+ event: 'feedback',
8
+ data: { success }
9
+ });
10
+ };
11
+
12
+ export const feedbackClickEpic = async (state: RootState, position: number) => {
13
+ const { search, settings } = state;
14
+ return await sendFeedbackByApi(settings, search.sessionId, search.requestId, {
15
+ event: "click",
16
+ data: { positions: [position] },
17
+ });
15
18
  };
16
19
 
17
- export const feedbackClickEpic = async (state: any, position: number) => {
20
+ export const feedbackTextSearchEpic = async (state: RootState, query: string, page: number, productIds: string[]) => {
18
21
  try {
19
22
  const { search, settings } = state;
20
- const api = new NyrisAPI(settings);
21
- const sessionId = search.sessionId || search.requestId;
22
- if (sessionId && state.search.requestId) {
23
- await api.sendFeedback(sessionId, state.search.requestId, {
24
- event: "click",
25
- data: { positions: [position] },
26
- });
27
- }
23
+ const eventData = {
24
+ query,
25
+ page,
26
+ product_ids: productIds,
27
+ };
28
+ const textSearchEvent = { event: "text-search", data: eventData };
29
+ // @ts-ignore
30
+ return await sendFeedbackByApi(settings, search.sessionId, search.requestId, textSearchEvent);
28
31
  } catch (error) {
29
- console.log("error feedbackClickEpic", feedbackClickEpic);
32
+ console.log("error feedbackTextSearchEpic", error);
30
33
  }
31
34
  };
32
35
 
33
- export const feedbackRegionEpic = async (state: any, region: any) => {
34
- try {
35
- const { search, settings } = state;
36
- const api = new NyrisAPI(settings);
37
- const sessionId = search.sessionId || search.requestId;
38
- const { x1, x2, y1, y2 } = region;
39
- if (sessionId && search.requestId) {
40
- await api.sendFeedback(sessionId, search.requestId, {
36
+ export const feedbackRegionEpic = async (state: RootState, region: RectCoords) => {
37
+ const {settings, search} = state;
38
+ const {sessionId, requestId } = search;
39
+ const { x1, x2, y1, y2 } = region;
40
+ const payload : FeedbackEventPayload = {
41
41
  event: "region",
42
- data: { rect: { x: x1, y: y1, w: x2 - x1, h: y2 - y1 } },
43
- });
44
- }
45
- } catch (error) {
46
- console.log("error feedbackRegionEpic", error);
47
- }
42
+ data: { rect: { x: x1, y: y1, w: x2 - x1, h: y2 - y1 } }
43
+ };
44
+ return await sendFeedbackByApi(settings, sessionId, requestId, payload);
48
45
  };
49
46
 
50
47
  export const sendFeedbackByApi = async (
51
- settings: any,
52
- sessionId: any,
53
- requestId: any,
54
- payload: any
48
+ settings: NyrisAPISettings,
49
+ sessionId: string | undefined,
50
+ requestId: string | undefined,
51
+ payload: FeedbackEventPayload
55
52
  ) => {
56
53
  const api = new NyrisAPI(settings);
57
- try {
58
- const dataByApi = await api
59
- .sendFeedback(sessionId, requestId, payload)
60
- .then((res) => {});
61
- console.log("dataByApi", dataByApi);
62
- } catch (error) {
63
- console.log("error sendFeedbackByApi321", error);
54
+ if (sessionId && requestId) {
55
+ try {
56
+ const dataByApi = await api
57
+ .sendFeedback(sessionId, requestId, payload)
58
+ .then((res) => {});
59
+ console.log("dataByApi", dataByApi);
60
+ } catch (error) {
61
+ console.log("error sendFeedbackByApi321", error);
62
+ }
64
63
  }
65
64
  };
@@ -1,107 +1,40 @@
1
- import {ImageSearchOptions, NyrisAPISettings, selectFirstCenteredRegion, urlOrBlobToCanvas} from "@nyris/nyris-api";
1
+ import {
2
+ NyrisAPISettings,
3
+ RectCoords,
4
+ selectFirstCenteredRegion,
5
+ urlOrBlobToCanvas
6
+ } from "@nyris/nyris-api";
2
7
  import NyrisAPI from "@nyris/nyris-api";
3
- import { fileOrBlobToCanvas, rectToCrop } from "./nyris";
8
+ import {isEqual} from "lodash";
4
9
 
5
- export const serviceImage = async (file: any, settings: NyrisAPISettings) => {
6
- try {
7
- const nyrisApi = new NyrisAPI(settings);
8
- const randomId = Math.random().toString();
10
+ export const defaultRect = {x1: 0, x2: 1, y1: 0, y2: 1};
9
11
 
10
- const image = await fileOrBlobToCanvas(file);
11
- const imageFileCanvas = { canvas: image, id: randomId };
12
+ export const createImage = async (fileOrUrl: File|string|HTMLCanvasElement) => {
13
+ const image = fileOrUrl instanceof HTMLCanvasElement ? fileOrUrl : await urlOrBlobToCanvas(fileOrUrl);
14
+ return image;
15
+ }
12
16
 
13
- const regions = await nyrisApi.findRegions(image);
14
- const searchRegion = selectFirstCenteredRegion(regions, 0.3, {x1: 0, x2: 1, y1: 0, y2: 1});
17
+ export const findRegions = async (image: HTMLCanvasElement, settings: NyrisAPISettings) => {
18
+ const nyrisApi = new NyrisAPI(settings);
19
+ let regions = await nyrisApi.findRegions(image);
15
20
 
16
- let options : ImageSearchOptions = {
17
- ...settings,
18
- cropRect: searchRegion
19
- };
20
-
21
- const { results, requestId, duration, categoryPredictions, codes } =
22
- await nyrisApi.findByImage(image, options);
23
- const payload = {
24
- results,
25
- requestId,
26
- categoryPredictions,
27
- codes,
28
- duration,
29
- regions,
30
- requestImage: imageFileCanvas,
31
- selectedRegion: searchRegion
32
- };
33
-
34
- return payload;
35
- } catch (error) {
36
- console.log("error serviceImage", error);
37
- return;
21
+ const selectedRegion = selectFirstCenteredRegion(regions, 0.3, defaultRect);
22
+ return {
23
+ selectedRegion: isEqual(selectedRegion, defaultRect) ? undefined : selectedRegion,
24
+ regions
38
25
  }
39
26
  };
40
27
 
41
- export const serviceImageNonRegion = async (
42
- file: any,
43
- stateStore: any,
44
- rectCoords: any
45
- ) => {
46
- const { settings } = stateStore;
47
- const api = new NyrisAPI(settings);
48
- const image = await urlOrBlobToCanvas(file);
49
- const randomId = Math.random().toString();
50
- const imageFileCanvas = { canvas: image, id: randomId };
51
- let options: ImageSearchOptions = {
52
- cropRect: rectCoords,
53
- };
54
- try {
55
- const { results, duration, requestId, categoryPredictions, codes } =
56
- await api.findByImage(image, options);
57
- return {
58
- results,
59
- requestId,
60
- duration,
61
- categoryPredictions,
62
- codes,
63
- requestImage: imageFileCanvas,
64
- };
65
- } catch (e) {
66
- console.warn("search failed serviceImageNonRegion", e);
28
+ export const findByImage = (image: HTMLCanvasElement, settings: NyrisAPISettings, region?: RectCoords) => {
29
+ const nyrisApi = new NyrisAPI(settings);
30
+ let options = {};
31
+ if (region) {
32
+ options = { cropRect: region };
67
33
  }
34
+ return nyrisApi.findByImage(image, options);
68
35
  };
69
36
 
70
- export const searchImageByPosition = async (
71
- image: HTMLCanvasElement,
72
- stateStore: any,
73
- region?: any
74
- ) => {
75
- try {
76
- const { settings } = stateStore;
77
-
78
- let options = settings;
79
- const nyrisApi = new NyrisAPI(settings);
80
- if (region) {
81
- let { x1, x2, y1, y2 } = region;
82
- let crop = rectToCrop({
83
- x1: x1 * image.width,
84
- x2: x2 * image.width,
85
- y1: y1 * image.height,
86
- y2: y2 * image.height,
87
- });
88
- options = {
89
- ...options,
90
- crop,
91
- };
92
- }
93
- const { results, duration, requestId, categoryPredictions, codes } =
94
- await nyrisApi.findByImage(image, options);
95
- const payload = {
96
- results,
97
- requestId,
98
- categoryPredictions,
99
- codes,
100
- duration,
101
- regions: region,
102
- };
103
- return payload;
104
- } catch (error: any) {
105
- console.log("error searchImageByPosition", error);
106
- }
37
+ export const findByCadFile = (file: File, settings: NyrisAPISettings) => {
38
+ const nyrisApi = new NyrisAPI(settings);
39
+ return nyrisApi.findByCad(file, {});
107
40
  };
@@ -5,16 +5,13 @@ const httpClient = axios.create();
5
5
 
6
6
  export const createSessionByApi = async (settings: NyrisAPISettings) => {
7
7
  const { apiKey, baseUrl} = settings;
8
- try {
9
- let headers: any = {
10
- "X-Api-Key": apiKey,
11
- };
12
- return await httpClient.request({
13
- method: "POST",
14
- url: `${baseUrl}/find/v1/session`,
15
- headers,
16
- });
17
- } catch (error: any) {
18
- console.log("error createAction:", error);
19
- }
8
+ let headers = {
9
+ "X-Api-Key": apiKey,
10
+ };
11
+ let response = await httpClient.request({
12
+ method: "POST",
13
+ url: `${baseUrl}/find/v1/session`,
14
+ headers,
15
+ });
16
+ return response.data.session;
20
17
  };
@@ -27,27 +27,6 @@ export interface SearchServiceSettings {
27
27
  useRecommendations: boolean
28
28
  }
29
29
 
30
- export interface ImageSearchOptions {
31
- geoLocation?: { lat: number, lon: number, dist: number };
32
- crop?: { x: number, y: number, w: number, h: number };
33
- maxWidth: number;
34
- maxHeight: number;
35
- useRecommendations: boolean;
36
- jpegQuality: number;
37
- }
38
-
39
- export interface RectCoords {
40
- x1: number,
41
- y1: number,
42
- x2: number,
43
- y2: number
44
- }
45
-
46
- export type Region = {
47
- className?: string,
48
- confidence?: number
49
- } & RectCoords
50
-
51
30
  export interface Crop {
52
31
  x: number,
53
32
  y: number,
@@ -60,23 +39,12 @@ export interface WH {
60
39
  h: number
61
40
  }
62
41
 
63
- // export type AppState = {
64
- // search: SearchState,
65
- // settings: SearchServiceSettings,
66
- // nyrisDesign: NyrisAppState
67
- // };
68
-
69
- // export type AppAction =
70
- // | SearchAction
71
- // | NyrisAction
72
-
73
-
74
42
  export interface Result {
75
43
  position: number,
76
44
  sku?: string,
77
45
  title?: string,
78
46
  l?: string,
79
47
  img?: { url?: string },
80
- // There can be also any other ddata
48
+ // There can be also any other data
81
49
  [x: string]: any
82
50
  }
package/src/types.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import {NyrisAPISettings} from "@nyris/nyris-api";
2
- import { NyrisAction } from "Store/common";
3
2
  import { NyrisAppState } from "Store/Nyris";
4
- import { SearchAction, SearchState } from "Store/Search";
3
+ import { SearchState } from "Store/Search";
5
4
 
6
5
  export interface MDSettings {
7
6
  customFontFamily?: string,
@@ -21,6 +20,12 @@ export interface MDSettings {
21
20
  active?: boolean
22
21
  }
23
22
 
23
+ export interface AlgoliaSettings {
24
+ apiKey: string,
25
+ appId: string,
26
+ indexName: string
27
+ }
28
+
24
29
  export interface AppSettings extends NyrisAPISettings {
25
30
  exampleImages: string[],
26
31
  preview: boolean,
@@ -29,7 +34,8 @@ export interface AppSettings extends NyrisAPISettings {
29
34
  resultTemplate?: string,
30
35
  regions: boolean,
31
36
  instantRedirectPatterns: string[],
32
- themePage: ThemeChoice
37
+ themePage: ThemeChoice,
38
+ algolia?: AlgoliaSettings
33
39
  }
34
40
 
35
41
  export interface DefaultThemeSettings {
@@ -52,10 +58,6 @@ export type AppState = {
52
58
  nyrisDesign: NyrisAppState
53
59
  };
54
60
 
55
- export type AppAction =
56
- | SearchAction
57
- | NyrisAction
58
-
59
61
  export interface CanvasWithId {
60
62
  canvas: HTMLCanvasElement
61
63
  id: string
@@ -84,3 +86,6 @@ export interface SearchServiceSettings {
84
86
  useRecommendations: boolean
85
87
  }
86
88
 
89
+ export interface AlgoliaResult {
90
+ sku: string
91
+ }