@nyris/nyris-webapp 0.2.5 → 0.3.2

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 (199) hide show
  1. package/build/asset-manifest.json +32 -18
  2. package/build/index.html +1 -1
  3. package/build/js/test.js +62 -0
  4. package/build/{precache-manifest.497998bf0df450969bab5608621be10a.js → precache-manifest.8f85a4fff2063a7498a608ec69549bb1.js} +89 -13
  5. package/build/service-worker.js +1 -1
  6. package/build/static/css/2.8285176a.chunk.css +2 -0
  7. package/build/static/css/2.8285176a.chunk.css.map +1 -0
  8. package/build/static/css/main.6676fe1f.chunk.css +2 -0
  9. package/build/static/css/main.6676fe1f.chunk.css.map +1 -0
  10. package/build/static/js/2.efc0ab83.chunk.js +3 -0
  11. package/build/static/js/2.efc0ab83.chunk.js.LICENSE.txt +133 -0
  12. package/build/static/js/2.efc0ab83.chunk.js.map +1 -0
  13. package/build/static/js/main.3bfed050.chunk.js +2 -0
  14. package/build/static/js/main.3bfed050.chunk.js.map +1 -0
  15. package/build/static/js/{runtime-main.f5553a9b.js → runtime-main.b418ff16.js} +1 -1
  16. package/build/static/js/{runtime-main.f5553a9b.js.map → runtime-main.b418ff16.js.map} +1 -1
  17. package/build/static/media/Fill.37094b44.svg +3 -0
  18. package/build/static/media/Montserrat-Bold.5a052e98.otf +0 -0
  19. package/build/static/media/Montserrat-Light.21789e89.otf +0 -0
  20. package/build/static/media/Montserrat-Medium.a53e0373.otf +0 -0
  21. package/build/static/media/Montserrat-Regular.71cdc681.otf +0 -0
  22. package/build/static/media/Montserrat-SemiBold.f613d915.otf +0 -0
  23. package/build/static/media/Rectangle.4dd8b747.png +0 -0
  24. package/build/static/media/admin.9529c7f6.svg +3 -0
  25. package/build/static/media/bg-support-page.6ac55268.svg +9 -0
  26. package/build/static/media/book_mark.8e294c0b.svg +3 -0
  27. package/build/static/media/icon_dislike.94607ca6.svg +3 -0
  28. package/build/static/media/icon_like.a4fb1b18.svg +3 -0
  29. package/build/static/media/icon_modal_image.3068d0ea.svg +21 -0
  30. package/build/static/media/icon_search_image.c2c728c0.svg +3 -0
  31. package/build/static/media/nyris_logo.22d8f250.svg +3 -0
  32. package/build/static/media/reload_icon.4b579a74.svg +3 -0
  33. package/build/static/media/save_search.bebaeebf.svg +3 -0
  34. package/build/static/media/support.289c3a3c.svg +3 -0
  35. package/build/static/media/translate_icon.f0492297.svg +3 -0
  36. package/package.json +30 -6
  37. package/public/js/test.js +62 -0
  38. package/src/App.css +27 -11
  39. package/src/App.tsx +19 -235
  40. package/src/Router.tsx +97 -0
  41. package/src/Store/Auth.ts +44 -0
  42. package/src/Store/Nyris.ts +77 -0
  43. package/src/Store/Search.ts +269 -0
  44. package/src/Store/Store.ts +46 -0
  45. package/src/Store/common.d.ts +10 -0
  46. package/src/{epics → Store/epics}/feedback.ts +0 -0
  47. package/src/{epics → Store/epics}/types.ts +1 -1
  48. package/src/common/assets/fonts/Montserrat_OTF/Montserrat-Bold.otf +0 -0
  49. package/src/common/assets/fonts/Montserrat_OTF/Montserrat-Light.otf +0 -0
  50. package/src/common/assets/fonts/Montserrat_OTF/Montserrat-Medium.otf +0 -0
  51. package/src/common/assets/fonts/Montserrat_OTF/Montserrat-Regular.otf +0 -0
  52. package/src/common/assets/fonts/Montserrat_OTF/Montserrat-SemiBold.otf +0 -0
  53. package/src/{fonts → common/assets/fonts}/roboto-bold-webfont.woff +0 -0
  54. package/src/{fonts → common/assets/fonts}/roboto-bold-webfont.woff2 +0 -0
  55. package/src/{fonts → common/assets/fonts}/roboto-italic-webfont.woff +0 -0
  56. package/src/{fonts → common/assets/fonts}/roboto-italic-webfont.woff2 +0 -0
  57. package/src/{fonts → common/assets/fonts}/roboto-regular-webfont.woff +0 -0
  58. package/src/{fonts → common/assets/fonts}/roboto-regular-webfont.woff2 +0 -0
  59. package/src/{fonts → common/assets/fonts}/robotocondensed-bold-webfont.woff +0 -0
  60. package/src/{fonts → common/assets/fonts}/robotocondensed-bold-webfont.woff2 +0 -0
  61. package/src/{fonts → common/assets/fonts}/robotocondensed-bolditalic-webfont.woff +0 -0
  62. package/src/{fonts → common/assets/fonts}/robotocondensed-bolditalic-webfont.woff2 +0 -0
  63. package/src/common/assets/icons/Fill.png +0 -0
  64. package/src/common/assets/icons/Fill.svg +3 -0
  65. package/src/common/assets/icons/Icon_wechat.png +0 -0
  66. package/src/common/assets/icons/Icon_whatsapp.png +0 -0
  67. package/src/common/assets/icons/admin.png +0 -0
  68. package/src/common/assets/icons/admin.svg +3 -0
  69. package/src/common/assets/icons/book_mark.png +0 -0
  70. package/src/common/assets/icons/book_mark.svg +3 -0
  71. package/src/common/assets/icons/icon_barcode.png +0 -0
  72. package/src/common/assets/icons/icon_camera.png +0 -0
  73. package/src/common/assets/icons/icon_dislike.svg +3 -0
  74. package/src/common/assets/icons/icon_disslike.png +0 -0
  75. package/src/common/assets/icons/icon_email.png +0 -0
  76. package/src/common/assets/icons/icon_like.png +0 -0
  77. package/src/common/assets/icons/icon_like.svg +3 -0
  78. package/src/common/assets/icons/icon_modal_image.png +0 -0
  79. package/src/common/assets/icons/icon_modal_image.svg +21 -0
  80. package/src/common/assets/icons/icon_picture.png +0 -0
  81. package/src/common/assets/icons/icon_search_image.png +0 -0
  82. package/src/common/assets/icons/icon_search_image.svg +3 -0
  83. package/src/common/assets/icons/nyris_logo.svg +3 -0
  84. package/src/common/assets/icons/reload_icon.png +0 -0
  85. package/src/common/assets/icons/reload_icon.svg +3 -0
  86. package/src/common/assets/icons/save_search.png +0 -0
  87. package/src/common/assets/icons/save_search.svg +3 -0
  88. package/src/common/assets/icons/setting_search_icon.png +0 -0
  89. package/src/common/assets/icons/support.png +0 -0
  90. package/src/common/assets/icons/support.svg +3 -0
  91. package/src/common/assets/icons/translate_icon.png +0 -0
  92. package/src/common/assets/icons/translate_icon.svg +3 -0
  93. package/src/common/assets/icons/view_off.png +0 -0
  94. package/src/common/assets/images/Rectangle.png +0 -0
  95. package/src/common/assets/images/bg-support-page.svg +9 -0
  96. package/src/{images → common/assets/images}/fav/android-icon-192x192.png +0 -0
  97. package/src/{images → common/assets/images}/fav/apple-icon-114x114.png +0 -0
  98. package/src/{images → common/assets/images}/fav/apple-icon-120x120.png +0 -0
  99. package/src/{images → common/assets/images}/fav/apple-icon-144x144.png +0 -0
  100. package/src/{images → common/assets/images}/fav/apple-icon-152x152.png +0 -0
  101. package/src/{images → common/assets/images}/fav/apple-icon-180x180.png +0 -0
  102. package/src/{images → common/assets/images}/fav/apple-icon-57x57.png +0 -0
  103. package/src/{images → common/assets/images}/fav/apple-icon-60x60.png +0 -0
  104. package/src/{images → common/assets/images}/fav/apple-icon-72x72.png +0 -0
  105. package/src/{images → common/assets/images}/fav/apple-icon-76x76.png +0 -0
  106. package/src/{images → common/assets/images}/fav/browserconfig.xml +0 -0
  107. package/src/{images → common/assets/images}/fav/favicon-16x16.png +0 -0
  108. package/src/{images → common/assets/images}/fav/favicon-32x32.png +0 -0
  109. package/src/{images → common/assets/images}/fav/favicon-96x96.png +0 -0
  110. package/src/{images → common/assets/images}/fav/manifest.json +0 -0
  111. package/src/{images → common/assets/images}/ic_cam.png +0 -0
  112. package/src/{images → common/assets/images}/ic_cam.svg +0 -0
  113. package/src/{images → common/assets/images}/ic_cam_large.png +0 -0
  114. package/src/{images → common/assets/images}/ic_cam_large.svg +0 -0
  115. package/src/{images → common/assets/images}/ic_cam_large_noimage.png +0 -0
  116. package/src/{images → common/assets/images}/ic_close_feedback.png +0 -0
  117. package/src/{images → common/assets/images}/ic_close_feedback.svg +0 -0
  118. package/src/{images → common/assets/images}/ic_shopNow.png +0 -0
  119. package/src/{images → common/assets/images}/ic_shopNow.svg +0 -0
  120. package/src/{images → common/assets/images}/ic_shopNowLight.png +0 -0
  121. package/src/{images → common/assets/images}/ic_shopNowLight.svg +0 -0
  122. package/src/common/assets/images/image_test.png +0 -0
  123. package/src/{images → common/assets/images}/nyris_logo.png +0 -0
  124. package/src/{images → common/assets/images}/rewe.svg +0 -0
  125. package/src/{images → common/assets/images}/sectionTransBack.png +0 -0
  126. package/src/{images → common/assets/images}/sectionTransBack.svg +0 -0
  127. package/src/{images → common/assets/images}/sectionTransTop.png +0 -0
  128. package/src/{images → common/assets/images}/sectionTransTop.svg +0 -0
  129. package/src/components/DetailItem.tsx +175 -0
  130. package/src/components/DragDropFile.tsx +188 -0
  131. package/src/components/ExampleImages.tsx +32 -17
  132. package/src/components/Feedback.tsx +87 -48
  133. package/src/components/FilterComponent.tsx +33 -0
  134. package/src/components/Footer.tsx +29 -0
  135. package/src/components/FooterMD.tsx +54 -0
  136. package/src/components/FooterNewVersion.tsx +12 -0
  137. package/src/components/FooterResult.tsx +47 -0
  138. package/src/components/Header.tsx +35 -0
  139. package/src/components/HeaderMd.tsx +39 -0
  140. package/src/components/HeaderNewVersion.tsx +92 -0
  141. package/src/components/Layout.tsx +46 -0
  142. package/src/components/LoadingScreen/index.tsx +29 -0
  143. package/src/components/Navigation.tsx +34 -0
  144. package/src/components/Panigation/Pagination.tsx +140 -0
  145. package/src/components/Panigation/cx.js +3 -0
  146. package/src/components/Panigation/isModifierClick.js +10 -0
  147. package/src/components/Result.tsx +186 -113
  148. package/src/components/Saved/AllItem.tsx +32 -0
  149. package/src/components/Saved/Category.tsx +16 -0
  150. package/src/components/carousel/DefaultCarousel.tsx +48 -0
  151. package/src/components/common.d.ts +9 -0
  152. package/src/components/common.scss +54 -0
  153. package/src/components/default-select.tsx +44 -0
  154. package/src/components/hitItem/hits.tsx +50 -0
  155. package/src/components/hitItem/infinitiHits.tsx +33 -0
  156. package/src/components/input/inputSearch.tsx +77 -0
  157. package/src/components/modal/DefaultModal.tsx +28 -0
  158. package/src/components/preview/preview.tsx +433 -0
  159. package/src/components/results/ItemResult.tsx +155 -0
  160. package/src/components/search/ListSearch.tsx +209 -0
  161. package/src/defaults.ts +4 -3
  162. package/src/index.css +577 -306
  163. package/src/index.tsx +39 -187
  164. package/src/modules/LandingPage/common.scss +1304 -0
  165. package/src/modules/LandingPage/indexApp.tsx +474 -0
  166. package/src/modules/LandingPage/indexAppMD.tsx +494 -0
  167. package/src/modules/LandingPage/indexNewVersion.tsx +117 -0
  168. package/src/page/Auth/login.tsx +7 -0
  169. package/src/page/Exception/404.tsx +11 -0
  170. package/src/page/History/index.tsx +76 -0
  171. package/src/page/Profile/index.tsx +87 -0
  172. package/src/page/Saved/MockData.ts +223 -0
  173. package/src/page/Saved/index.tsx +166 -0
  174. package/src/page/Support/index.tsx +160 -0
  175. package/src/page/result/MockData.ts +36 -0
  176. package/src/page/result/index.tsx +473 -0
  177. package/src/services/Feedback.ts +65 -0
  178. package/src/services/findByImage.ts +24 -0
  179. package/src/services/findRegionsCustom.ts +212 -0
  180. package/src/services/image.ts +110 -0
  181. package/src/services/nyris.ts +123 -0
  182. package/src/services/session.ts +20 -0
  183. package/src/services/types.ts +96 -0
  184. package/src/types.ts +43 -3
  185. package/tsconfig.json +3 -8
  186. package/build/static/css/2.43a1c8b7.chunk.css +0 -2
  187. package/build/static/css/2.43a1c8b7.chunk.css.map +0 -1
  188. package/build/static/css/main.f6ed5f12.chunk.css +0 -2
  189. package/build/static/css/main.f6ed5f12.chunk.css.map +0 -1
  190. package/build/static/js/2.a591d52a.chunk.js +0 -3
  191. package/build/static/js/2.a591d52a.chunk.js.LICENSE.txt +0 -79
  192. package/build/static/js/2.a591d52a.chunk.js.map +0 -1
  193. package/build/static/js/main.28bb3581.chunk.js +0 -2
  194. package/build/static/js/main.28bb3581.chunk.js.map +0 -1
  195. package/src/AppMD.tsx +0 -320
  196. package/src/actions/nyrisAppActions.ts +0 -76
  197. package/src/actions/searchActions.ts +0 -143
  198. package/src/epics/index.ts +0 -149
  199. package/src/epics/search.ts +0 -114
@@ -0,0 +1,212 @@
1
+ import {
2
+ ImageSearchOptions,
3
+ Region,
4
+ Result,
5
+ SearchServiceSettings,
6
+ } from "./types";
7
+ // import {canvasToJpgBlob, getElementSize, getThumbSizeArea, toCanvas} from "./nyris";
8
+ import axios, { AxiosInstance } from "axios";
9
+ import {
10
+ canvasToJpgBlob,
11
+ getElementSize,
12
+ getThumbSizeArea,
13
+ toCanvas,
14
+ } from "./nyris";
15
+
16
+ export interface RegionData {
17
+ rect: {
18
+ x: number;
19
+ y: number;
20
+ w: number;
21
+ h: number;
22
+ };
23
+ }
24
+
25
+ interface SearchResult {
26
+ results: Result[];
27
+ requestId: string;
28
+ categoryPredictions: any[];
29
+ codes: any[];
30
+ duration: number;
31
+ }
32
+
33
+ export default class NyrisAPICT {
34
+ private readonly httpClient: AxiosInstance;
35
+ private readonly imageMatchingUrl: string;
36
+ private readonly regionProposalUrl: string;
37
+ private readonly responseFormat: string;
38
+ private imageMatchingUrlBySku: string;
39
+ private imageMatchingSubmitManualUrl: string;
40
+ private feedbackUrl: string;
41
+
42
+ constructor(private settings: SearchServiceSettings) {
43
+ this.httpClient = axios.create();
44
+ this.imageMatchingUrl =
45
+ this.settings.imageMatchingUrl || "https://api.nyris.io/find/v1";
46
+ this.imageMatchingUrlBySku =
47
+ this.settings.imageMatchingUrlBySku ||
48
+ "https://api.nyris.io/recommend/v1/";
49
+ this.imageMatchingSubmitManualUrl =
50
+ this.settings.imageMatchingSubmitManualUrl ||
51
+ "https://api.nyris.io/find/v1/manual/";
52
+ this.feedbackUrl =
53
+ this.settings.feedbackUrl || "https://api.nyris.io/feedback/v1/";
54
+ this.regionProposalUrl =
55
+ this.settings.regionProposalUrl ||
56
+ "https://api.nyris.io/find/v1/regions/";
57
+ this.responseFormat =
58
+ this.settings.responseFormat || "application/offers.nyris+json";
59
+ }
60
+
61
+ /**
62
+ * Find significant sections in the image.
63
+ * @param canvas Canvas, video or image to search with.
64
+ * @param options See [[ImageSearchOptions]].
65
+ * @returns A list of regions, see [[Region]].
66
+ */
67
+ async findRegions(
68
+ canvas: HTMLCanvasElement | HTMLVideoElement | HTMLImageElement,
69
+ options: ImageSearchOptions
70
+ ): Promise<Region[]> {
71
+ let [origW, origH] = getElementSize(canvas);
72
+ let { w: scaledW, h: scaledH } = getThumbSizeArea(
73
+ options.maxWidth,
74
+ options.maxHeight,
75
+ origW,
76
+ origH
77
+ );
78
+ let resizedCroppedCanvas = toCanvas(canvas, { w: scaledW, h: scaledH });
79
+ let blob = await canvasToJpgBlob(resizedCroppedCanvas, options.jpegQuality);
80
+
81
+ const headers = {
82
+ "Content-Type": "image/jpeg",
83
+ "X-Api-Key": this.settings.apiKey,
84
+ };
85
+ let response = await this.httpClient.request<any[]>({
86
+ method: "POST",
87
+ url: this.regionProposalUrl,
88
+ data: blob,
89
+ headers,
90
+ });
91
+ let regions: any[] = response.data;
92
+ return regions.map((r) => ({
93
+ className: r.className,
94
+ confidence: r.confidence,
95
+ x1: r.region.left / scaledW,
96
+ x2: r.region.right / scaledW,
97
+ y1: r.region.top / scaledH,
98
+ y2: r.region.bottom / scaledH,
99
+ }));
100
+ }
101
+
102
+ private async prepareImage(
103
+ canvas: HTMLCanvasElement | HTMLImageElement | HTMLVideoElement,
104
+ options: ImageSearchOptions
105
+ ): Promise<{ bytes: Blob; region?: RegionData }> {
106
+ let [w, h] = getElementSize(canvas);
107
+ let crop = options.crop
108
+ ? options.crop
109
+ : {
110
+ x: 0,
111
+ y: 0,
112
+ w: w,
113
+ h: h,
114
+ };
115
+ let region: RegionData | undefined = undefined;
116
+ if (options.crop) {
117
+ region = {
118
+ rect: {
119
+ w: Math.min(1, crop.w / w),
120
+ h: Math.min(1, crop.h / h),
121
+ x: Math.min(1, crop.x / w),
122
+ y: Math.min(1, crop.y / h),
123
+ },
124
+ };
125
+ }
126
+ let scaledSize = getThumbSizeArea(
127
+ options.maxWidth,
128
+ options.maxHeight,
129
+ crop.w,
130
+ crop.h
131
+ );
132
+ let resizedCroppedCanvas = toCanvas(canvas, scaledSize, undefined, crop);
133
+ let bytes = await canvasToJpgBlob(
134
+ resizedCroppedCanvas,
135
+ options.jpegQuality
136
+ );
137
+
138
+ return { bytes, region };
139
+ }
140
+
141
+ async findByImage(
142
+ canvas: HTMLCanvasElement | HTMLImageElement | HTMLVideoElement,
143
+ options: ImageSearchOptions
144
+ ): Promise<SearchResult> {
145
+ const image = await this.prepareImage(canvas, options);
146
+
147
+ if (this.settings.customSearchRequest)
148
+ return this.settings.customSearchRequest(image.bytes, this.httpClient); // TODO check if the interface is ok for hooks
149
+
150
+ let headers: any = {
151
+ "Content-Type": "image/jpeg",
152
+ "X-Api-Key": this.settings.apiKey,
153
+ "Accept-Language": "de,*;q=0.5",
154
+ Accept: this.responseFormat,
155
+ };
156
+ const xOptions = [];
157
+ if (this.settings.xOptions) xOptions.push(this.settings.xOptions as string);
158
+ if (options.useRecommendations) xOptions.push("+recommendations");
159
+ if (xOptions.length > 0) headers["X-Options"] = xOptions.join(" ");
160
+ let params = options.geoLocation
161
+ ? {
162
+ lat: options.geoLocation.lat.toString(),
163
+ lon: options.geoLocation.lon.toString(),
164
+ dist: options.geoLocation.dist.toString(),
165
+ }
166
+ : {};
167
+ // console.log("p", params, image.bytes);
168
+ let res: any = await this.httpClient.request<any>({
169
+ method: "POST",
170
+ url: this.imageMatchingUrl,
171
+ data: image.bytes,
172
+ params,
173
+ headers,
174
+ responseType: "json",
175
+ });
176
+ // console.log(res);
177
+ const categoryPredictions = Object.entries(
178
+ res.data.predicted_category || {}
179
+ )
180
+ .map(([name, score]) => ({
181
+ name: name,
182
+ score: score as number,
183
+ }))
184
+ .sort((a, b) => b.score - a.score);
185
+ let codes = res.data.barcodes || [];
186
+
187
+ let responseData = this.settings.responseHook
188
+ ? this.settings.responseHook(res.data)
189
+ : res.data;
190
+
191
+ let results: Result[] = responseData?.results.map(
192
+ (r: Result, i: number) => ({
193
+ ...r,
194
+ position: i,
195
+ })
196
+ );
197
+ const requestId = res.headers["x-matching-request"];
198
+ const duration = res.data.durationSeconds;
199
+ return { results, requestId, duration, categoryPredictions, codes };
200
+ }
201
+
202
+ async createSession(): Promise<{ data: any }> {
203
+ let headers: any = {
204
+ "X-Api-Key": this.settings.apiKey,
205
+ };
206
+ return await this.httpClient.request({
207
+ method: "POST",
208
+ url: `${this.imageMatchingUrl}/session`,
209
+ headers,
210
+ });
211
+ }
212
+ }
@@ -0,0 +1,110 @@
1
+ import { ImageSearchOptions, urlOrBlobToCanvas } from "@nyris/nyris-api";
2
+ import NyrisAPICT from "./findRegionsCustom";
3
+ import NyrisAPI from "@nyris/nyris-api";
4
+ import { fileOrBlobToCanvas, rectToCrop } from "./nyris";
5
+
6
+ export const serviceImage = async (file: any, stateStore: any) => {
7
+ try {
8
+ const { settings } = stateStore;
9
+ let options = settings;
10
+ const nyrisApi = new NyrisAPICT(settings);
11
+ const randomId = Math.random().toString();
12
+
13
+ const image: any = await fileOrBlobToCanvas(file);
14
+ const imageFileCanvas = { canvas: image, id: randomId };
15
+
16
+ const searchServiceSettings: any = {
17
+ ...settings,
18
+ responseHook: (r: any) => ({ offerInfos: r.results }),
19
+ };
20
+
21
+ const regions: any = await nyrisApi.findRegions(
22
+ image,
23
+ searchServiceSettings
24
+ );
25
+ const { results, requestId, duration, categoryPredictions, codes } =
26
+ await nyrisApi.findByImage(image, options);
27
+ const payload = {
28
+ results,
29
+ requestId,
30
+ categoryPredictions,
31
+ codes,
32
+ duration,
33
+ regions,
34
+ requestImage: imageFileCanvas,
35
+ };
36
+
37
+ return payload;
38
+ } catch (error) {
39
+ console.log("error serviceImage", error);
40
+ return;
41
+ }
42
+ };
43
+
44
+ export const serviceImageNonRegion = async (
45
+ file: any,
46
+ stateStore: any,
47
+ rectCoords: any
48
+ ) => {
49
+ const { settings } = stateStore;
50
+ const api = new NyrisAPI(settings);
51
+ const image = await urlOrBlobToCanvas(file);
52
+ const randomId = Math.random().toString();
53
+ const imageFileCanvas = { canvas: image, id: randomId };
54
+ let options: ImageSearchOptions = {
55
+ cropRect: rectCoords,
56
+ };
57
+ try {
58
+ const { results, duration, requestId, categoryPredictions, codes } =
59
+ await api.findByImage(image, options);
60
+ return {
61
+ results,
62
+ requestId,
63
+ duration,
64
+ categoryPredictions,
65
+ codes,
66
+ requestImage: imageFileCanvas,
67
+ };
68
+ } catch (e) {
69
+ console.warn("search failed serviceImageNonRegion", e);
70
+ }
71
+ };
72
+
73
+ export const searchImageByPosition = async (
74
+ image: HTMLCanvasElement,
75
+ stateStore: any,
76
+ region?: any
77
+ ) => {
78
+ try {
79
+ const { settings } = stateStore;
80
+
81
+ let options = settings;
82
+ const nyrisApi = new NyrisAPICT(settings);
83
+ if (region) {
84
+ let { x1, x2, y1, y2 } = region;
85
+ let crop = rectToCrop({
86
+ x1: x1 * image.width,
87
+ x2: x2 * image.width,
88
+ y1: y1 * image.height,
89
+ y2: y2 * image.height,
90
+ });
91
+ options = {
92
+ ...options,
93
+ crop,
94
+ };
95
+ }
96
+ const { results, duration, requestId, categoryPredictions, codes } =
97
+ await nyrisApi.findByImage(image, options);
98
+ const payload = {
99
+ results,
100
+ requestId,
101
+ categoryPredictions,
102
+ codes,
103
+ duration,
104
+ regions: region,
105
+ };
106
+ return payload;
107
+ } catch (error: any) {
108
+ console.log("error searchImageByPosition", error);
109
+ }
110
+ };
@@ -0,0 +1,123 @@
1
+ import loadImage from "blueimp-load-image";
2
+ import { Crop, WH } from "./types";
3
+
4
+ export function getElementSize(
5
+ elem: HTMLImageElement | HTMLVideoElement | HTMLCanvasElement
6
+ ) {
7
+ const img = elem as HTMLImageElement;
8
+ const video = elem as HTMLVideoElement;
9
+ return [
10
+ img.naturalWidth || video.videoWidth || elem.width,
11
+ img.naturalHeight || video.videoHeight || elem.height,
12
+ ];
13
+ }
14
+
15
+ export function getThumbSizeArea(
16
+ maxWidth: number,
17
+ maxHeight: number,
18
+ originalWidth: number,
19
+ originalHeight: number
20
+ ): WH {
21
+ const targetArea = maxWidth * maxHeight;
22
+
23
+ const aspectRatio = originalWidth / originalHeight;
24
+ const width = Math.sqrt(targetArea * aspectRatio);
25
+ return {
26
+ w: width,
27
+ h: width / aspectRatio,
28
+ };
29
+ }
30
+
31
+ // TODO get rid of crop type
32
+ export function toCanvas(
33
+ elem: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement,
34
+ newSize?: WH,
35
+ canvas?: HTMLCanvasElement,
36
+ crop?: Crop
37
+ ): HTMLCanvasElement {
38
+ let [ow, oh] = getElementSize(elem);
39
+ if (!crop) {
40
+ crop = {
41
+ x: 0,
42
+ y: 0,
43
+ w: ow,
44
+ h: oh,
45
+ };
46
+ }
47
+ const sx = crop.x;
48
+ const sy = crop.y;
49
+ const sw = crop.w;
50
+ const sh = crop.h;
51
+
52
+ const dw = (newSize && newSize.w) || ow;
53
+ const dh = (newSize && newSize.h) || oh;
54
+
55
+ if (!canvas) canvas = document.createElement("canvas");
56
+
57
+ canvas.width = dw;
58
+ canvas.height = dh;
59
+ // @ts-ignore
60
+ canvas.getContext("2d").drawImage(
61
+ elem,
62
+ sx,
63
+ sy,
64
+ sw,
65
+ sh,
66
+ 0,
67
+ 0, // dx dy
68
+ dw,
69
+ dh
70
+ );
71
+ return canvas;
72
+ }
73
+
74
+ export function canvasToJpgBlob(
75
+ canvas: HTMLCanvasElement,
76
+ quality: number
77
+ ): Promise<Blob> {
78
+ return new Promise((resolve, reject) => {
79
+ canvas.toBlob(
80
+ (blob) => {
81
+ if (blob) {
82
+ resolve(blob);
83
+ } else {
84
+ reject();
85
+ }
86
+ },
87
+ "image/jpeg",
88
+ quality
89
+ );
90
+ });
91
+ }
92
+
93
+ export const rectToCrop = ({ x1, x2, y1, y2 }: any): Crop => ({
94
+ x: x1,
95
+ y: y1,
96
+ w: x2 - x1,
97
+ h: y2 - y1,
98
+ });
99
+
100
+ export function fileOrBlobToCanvas(
101
+ file: File | string
102
+ ): Promise<HTMLCanvasElement> {
103
+ return new Promise((resolve, reject) => {
104
+ // File can also be an image element
105
+ loadImage(
106
+ file,
107
+ (data) => {
108
+ const c = data as HTMLCanvasElement;
109
+ if (c) {
110
+ resolve(c);
111
+ } else {
112
+ reject();
113
+ }
114
+ },
115
+ {
116
+ canvas: true,
117
+ orientation: true,
118
+ crossOrigin: "anonymous",
119
+ }
120
+ );
121
+
122
+ });
123
+ }
@@ -0,0 +1,20 @@
1
+ import NyrisAPI from "@nyris/nyris-api";
2
+ import axios, { AxiosInstance } from "axios";
3
+
4
+ const httpClient = axios.create();
5
+
6
+ export const createSessionByApi = async (state: any) => {
7
+ const { search, settings } = state;
8
+ try {
9
+ let headers: any = {
10
+ "X-Api-Key": settings.apiKey,
11
+ };
12
+ return await httpClient.request({
13
+ method: "POST",
14
+ url: `${settings.imageMatchingUrl}/session`,
15
+ headers,
16
+ });
17
+ } catch (error: any) {
18
+ console.log("error createAction:", error);
19
+ }
20
+ };
@@ -0,0 +1,96 @@
1
+ // import {SearchAction, SearchState} from "./actions/searchActions";
2
+ // import {NyrisAction, NyrisAppState} from "./actions/nyrisAppActions";
3
+
4
+ export interface MDSettings {
5
+ customFontFamily?: string,
6
+
7
+ appBarLogoUrl: string,
8
+ appBarTitle: string,
9
+ appBarCustomBackgroundColor?: string,
10
+ appBarCustomTextColor?: string,
11
+
12
+ primaryColor: string,
13
+ secondaryColor: string,
14
+ resultFirstRowProperty: string,
15
+ resultSecondRowProperty: string,
16
+
17
+ resultLinkText?: string,
18
+ resultLinkIcon?: string,
19
+ }
20
+
21
+ export interface SearchServiceSettings {
22
+ xOptions: boolean | string,
23
+ customSearchRequest?: ((file: Blob, client: any) => Promise<any>),
24
+ responseHook?: ((response: any) => any),
25
+ apiKey: string,
26
+ imageMatchingUrl?: string,
27
+ imageMatchingUrlBySku?: string,
28
+ imageMatchingSubmitManualUrl?: string,
29
+ regionProposalUrl?: string,
30
+ responseFormat?: string,
31
+ feedbackUrl?: string,
32
+ exampleImages: string[],
33
+ resultTemplate?: string,
34
+ noImageUrl?: string,
35
+ materialDesign?: MDSettings,
36
+ preview: boolean,
37
+ regions: boolean,
38
+ jpegQuality: number,
39
+ maxWidth: number,
40
+ maxHeight: number,
41
+ useRecommendations: boolean
42
+ }
43
+
44
+ export interface ImageSearchOptions {
45
+ geoLocation?: { lat: number, lon: number, dist: number };
46
+ crop?: { x: number, y: number, w: number, h: number };
47
+ maxWidth: number;
48
+ maxHeight: number;
49
+ useRecommendations: boolean;
50
+ jpegQuality: number;
51
+ }
52
+
53
+ export interface RectCoords {
54
+ x1: number,
55
+ y1: number,
56
+ x2: number,
57
+ y2: number
58
+ }
59
+
60
+ export type Region = {
61
+ className?: string,
62
+ confidence?: number
63
+ } & RectCoords
64
+
65
+ export interface Crop {
66
+ x: number,
67
+ y: number,
68
+ w: number,
69
+ h: number
70
+ }
71
+
72
+ export interface WH {
73
+ w: number,
74
+ h: number
75
+ }
76
+
77
+ // export type AppState = {
78
+ // search: SearchState,
79
+ // settings: SearchServiceSettings,
80
+ // nyrisDesign: NyrisAppState
81
+ // };
82
+
83
+ // export type AppAction =
84
+ // | SearchAction
85
+ // | NyrisAction
86
+
87
+
88
+ export interface Result {
89
+ position: number,
90
+ sku?: string,
91
+ title?: string,
92
+ l?: string,
93
+ img?: { url?: string },
94
+ // There can be also any other ddata
95
+ [x: string]: any
96
+ }
package/src/types.ts CHANGED
@@ -1,6 +1,7 @@
1
- import {SearchAction, SearchState} from "./actions/searchActions";
2
- import {NyrisAction, NyrisAppState} from "./actions/nyrisAppActions";
3
1
  import {NyrisAPISettings} from "@nyris/nyris-api";
2
+ import { NyrisAction } from "Store/common";
3
+ import { NyrisAppState } from "Store/Nyris";
4
+ import { SearchAction, SearchState } from "Store/Search";
4
5
 
5
6
  export interface MDSettings {
6
7
  customFontFamily?: string,
@@ -17,6 +18,7 @@ export interface MDSettings {
17
18
 
18
19
  resultLinkText?: string,
19
20
  resultLinkIcon?: string,
21
+ active?: boolean
20
22
  }
21
23
 
22
24
  export interface AppSettings extends NyrisAPISettings {
@@ -27,7 +29,22 @@ export interface AppSettings extends NyrisAPISettings {
27
29
  resultTemplate?: string,
28
30
  regions: boolean,
29
31
  materialDesign?: MDSettings,
30
- instantRedirectPatterns: string[]
32
+ instantRedirectPatterns: string[],
33
+ themePage: ThemeChoice
34
+ }
35
+
36
+ export interface DefaultThemeSettings {
37
+ active: boolean
38
+ }
39
+
40
+ export interface SearchSuiteSettings {
41
+ active: boolean
42
+ }
43
+
44
+ export type ThemeChoice = {
45
+ default?: DefaultThemeSettings,
46
+ materialDesign?: MDSettings,
47
+ searchSuite?: SearchSuiteSettings
31
48
  }
32
49
 
33
50
  export type AppState = {
@@ -45,3 +62,26 @@ export interface CanvasWithId {
45
62
  id: string
46
63
  }
47
64
 
65
+ export interface SearchServiceSettings {
66
+ xOptions: boolean | string,
67
+ customSearchRequest?: ((file: Blob, client: any) => Promise<any>),
68
+ responseHook?: ((response: any) => any),
69
+ apiKey: string,
70
+ imageMatchingUrl?: string,
71
+ imageMatchingUrlBySku?: string,
72
+ imageMatchingSubmitManualUrl?: string,
73
+ regionProposalUrl?: string,
74
+ responseFormat?: string,
75
+ feedbackUrl?: string,
76
+ exampleImages: string[],
77
+ resultTemplate?: string,
78
+ noImageUrl?: string,
79
+ materialDesign?: MDSettings,
80
+ preview: boolean,
81
+ regions: boolean,
82
+ jpegQuality: number,
83
+ maxWidth: number,
84
+ maxHeight: number,
85
+ useRecommendations: boolean
86
+ }
87
+
package/tsconfig.json CHANGED
@@ -1,11 +1,8 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  "target": "es5",
4
- "lib": [
5
- "dom",
6
- "dom.iterable",
7
- "esnext"
8
- ],
4
+ "baseUrl": "src",
5
+ "lib": ["dom", "dom.iterable", "esnext"],
9
6
  "noErrorTruncation": true,
10
7
  "allowJs": true,
11
8
  "skipLibCheck": true,
@@ -20,7 +17,5 @@
20
17
  "noEmit": true,
21
18
  "jsx": "react"
22
19
  },
23
- "include": [
24
- "src"
25
- ]
20
+ "include": ["src"]
26
21
  }
@@ -1,2 +0,0 @@
1
- @font-face{font-family:"Roboto";font-style:normal;font-display:swap;font-weight:100;src:local("Roboto Thin "),local("Roboto-Thin"),url(../../static/media/roboto-latin-100.7370c367.woff2) format("woff2"),url(../../static/media/roboto-latin-100.5cb7edfc.woff) format("woff")}@font-face{font-family:"Roboto";font-style:italic;font-display:swap;font-weight:100;src:local("Roboto Thin italic"),local("Roboto-Thinitalic"),url(../../static/media/roboto-latin-100italic.f8b1df51.woff2) format("woff2"),url(../../static/media/roboto-latin-100italic.f9e8e590.woff) format("woff")}@font-face{font-family:"Roboto";font-style:normal;font-display:swap;font-weight:300;src:local("Roboto Light "),local("Roboto-Light"),url(../../static/media/roboto-latin-300.ef7c6637.woff2) format("woff2"),url(../../static/media/roboto-latin-300.b00849e0.woff) format("woff")}@font-face{font-family:"Roboto";font-style:italic;font-display:swap;font-weight:300;src:local("Roboto Light italic"),local("Roboto-Lightitalic"),url(../../static/media/roboto-latin-300italic.14286f3b.woff2) format("woff2"),url(../../static/media/roboto-latin-300italic.4df32891.woff) format("woff")}@font-face{font-family:"Roboto";font-style:normal;font-display:swap;font-weight:400;src:local("Roboto Regular "),local("Roboto-Regular"),url(../../static/media/roboto-latin-400.479970ff.woff2) format("woff2"),url(../../static/media/roboto-latin-400.60fa3c06.woff) format("woff")}@font-face{font-family:"Roboto";font-style:italic;font-display:swap;font-weight:400;src:local("Roboto Regular italic"),local("Roboto-Regularitalic"),url(../../static/media/roboto-latin-400italic.51521a2a.woff2) format("woff2"),url(../../static/media/roboto-latin-400italic.fe65b833.woff) format("woff")}@font-face{font-family:"Roboto";font-style:normal;font-display:swap;font-weight:500;src:local("Roboto Medium "),local("Roboto-Medium"),url(../../static/media/roboto-latin-500.020c97dc.woff2) format("woff2"),url(../../static/media/roboto-latin-500.87284894.woff) format("woff")}@font-face{font-family:"Roboto";font-style:italic;font-display:swap;font-weight:500;src:local("Roboto Medium italic"),local("Roboto-Mediumitalic"),url(../../static/media/roboto-latin-500italic.db4a2a23.woff2) format("woff2"),url(../../static/media/roboto-latin-500italic.288ad9c6.woff) format("woff")}@font-face{font-family:"Roboto";font-style:normal;font-display:swap;font-weight:700;src:local("Roboto Bold "),local("Roboto-Bold"),url(../../static/media/roboto-latin-700.2735a3a6.woff2) format("woff2"),url(../../static/media/roboto-latin-700.adcde98f.woff) format("woff")}@font-face{font-family:"Roboto";font-style:italic;font-display:swap;font-weight:700;src:local("Roboto Bold italic"),local("Roboto-Bolditalic"),url(../../static/media/roboto-latin-700italic.da0e7178.woff2) format("woff2"),url(../../static/media/roboto-latin-700italic.81f57861.woff) format("woff")}@font-face{font-family:"Roboto";font-style:normal;font-display:swap;font-weight:900;src:local("Roboto Black "),local("Roboto-Black"),url(../../static/media/roboto-latin-900.9b3766ef.woff2) format("woff2"),url(../../static/media/roboto-latin-900.bb1e4dc6.woff) format("woff")}@font-face{font-family:"Roboto";font-style:italic;font-display:swap;font-weight:900;src:local("Roboto Black italic"),local("Roboto-Blackitalic"),url(../../static/media/roboto-latin-900italic.ebf6d164.woff2) format("woff2"),url(../../static/media/roboto-latin-900italic.28f91510.woff) format("woff")}
2
- /*# sourceMappingURL=2.43a1c8b7.chunk.css.map */
@@ -1 +0,0 @@
1
- {"version":3,"sources":["index.css"],"names":[],"mappings":"AACA,WACE,oBAAqB,CACrB,iBAAkB,CAClB,iBAAkB,CAClB,eAAgB,CAChB,4LAKF,CAGA,WACE,oBAAqB,CACrB,iBAAkB,CAClB,iBAAkB,CAClB,eAAgB,CAChB,oNAKF,CAGA,WACE,oBAAqB,CACrB,iBAAkB,CAClB,iBAAkB,CAClB,eAAgB,CAChB,8LAKF,CAGA,WACE,oBAAqB,CACrB,iBAAkB,CAClB,iBAAkB,CAClB,eAAgB,CAChB,sNAKF,CAGA,WACE,oBAAqB,CACrB,iBAAkB,CAClB,iBAAkB,CAClB,eAAgB,CAChB,kMAKF,CAGA,WACE,oBAAqB,CACrB,iBAAkB,CAClB,iBAAkB,CAClB,eAAgB,CAChB,0NAKF,CAGA,WACE,oBAAqB,CACrB,iBAAkB,CAClB,iBAAkB,CAClB,eAAgB,CAChB,gMAKF,CAGA,WACE,oBAAqB,CACrB,iBAAkB,CAClB,iBAAkB,CAClB,eAAgB,CAChB,wNAKF,CAGA,WACE,oBAAqB,CACrB,iBAAkB,CAClB,iBAAkB,CAClB,eAAgB,CAChB,4LAKF,CAGA,WACE,oBAAqB,CACrB,iBAAkB,CAClB,iBAAkB,CAClB,eAAgB,CAChB,oNAKF,CAGA,WACE,oBAAqB,CACrB,iBAAkB,CAClB,iBAAkB,CAClB,eAAgB,CAChB,8LAKF,CAGA,WACE,oBAAqB,CACrB,iBAAkB,CAClB,iBAAkB,CAClB,eAAgB,CAChB,sNAKF","file":"2.43a1c8b7.chunk.css","sourcesContent":["/* roboto-100normal - latin */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 100;\n src:\n local('Roboto Thin '),\n local('Roboto-Thin'),\n url('./files/roboto-latin-100.woff2') format('woff2'), /* Super Modern Browsers */\n url('./files/roboto-latin-100.woff') format('woff'); /* Modern Browsers */\n}\n\n/* roboto-100italic - latin */\n@font-face {\n font-family: 'Roboto';\n font-style: italic;\n font-display: swap;\n font-weight: 100;\n src:\n local('Roboto Thin italic'),\n local('Roboto-Thinitalic'),\n url('./files/roboto-latin-100italic.woff2') format('woff2'), /* Super Modern Browsers */\n url('./files/roboto-latin-100italic.woff') format('woff'); /* Modern Browsers */\n}\n\n/* roboto-300normal - latin */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 300;\n src:\n local('Roboto Light '),\n local('Roboto-Light'),\n url('./files/roboto-latin-300.woff2') format('woff2'), /* Super Modern Browsers */\n url('./files/roboto-latin-300.woff') format('woff'); /* Modern Browsers */\n}\n\n/* roboto-300italic - latin */\n@font-face {\n font-family: 'Roboto';\n font-style: italic;\n font-display: swap;\n font-weight: 300;\n src:\n local('Roboto Light italic'),\n local('Roboto-Lightitalic'),\n url('./files/roboto-latin-300italic.woff2') format('woff2'), /* Super Modern Browsers */\n url('./files/roboto-latin-300italic.woff') format('woff'); /* Modern Browsers */\n}\n\n/* roboto-400normal - latin */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 400;\n src:\n local('Roboto Regular '),\n local('Roboto-Regular'),\n url('./files/roboto-latin-400.woff2') format('woff2'), /* Super Modern Browsers */\n url('./files/roboto-latin-400.woff') format('woff'); /* Modern Browsers */\n}\n\n/* roboto-400italic - latin */\n@font-face {\n font-family: 'Roboto';\n font-style: italic;\n font-display: swap;\n font-weight: 400;\n src:\n local('Roboto Regular italic'),\n local('Roboto-Regularitalic'),\n url('./files/roboto-latin-400italic.woff2') format('woff2'), /* Super Modern Browsers */\n url('./files/roboto-latin-400italic.woff') format('woff'); /* Modern Browsers */\n}\n\n/* roboto-500normal - latin */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 500;\n src:\n local('Roboto Medium '),\n local('Roboto-Medium'),\n url('./files/roboto-latin-500.woff2') format('woff2'), /* Super Modern Browsers */\n url('./files/roboto-latin-500.woff') format('woff'); /* Modern Browsers */\n}\n\n/* roboto-500italic - latin */\n@font-face {\n font-family: 'Roboto';\n font-style: italic;\n font-display: swap;\n font-weight: 500;\n src:\n local('Roboto Medium italic'),\n local('Roboto-Mediumitalic'),\n url('./files/roboto-latin-500italic.woff2') format('woff2'), /* Super Modern Browsers */\n url('./files/roboto-latin-500italic.woff') format('woff'); /* Modern Browsers */\n}\n\n/* roboto-700normal - latin */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 700;\n src:\n local('Roboto Bold '),\n local('Roboto-Bold'),\n url('./files/roboto-latin-700.woff2') format('woff2'), /* Super Modern Browsers */\n url('./files/roboto-latin-700.woff') format('woff'); /* Modern Browsers */\n}\n\n/* roboto-700italic - latin */\n@font-face {\n font-family: 'Roboto';\n font-style: italic;\n font-display: swap;\n font-weight: 700;\n src:\n local('Roboto Bold italic'),\n local('Roboto-Bolditalic'),\n url('./files/roboto-latin-700italic.woff2') format('woff2'), /* Super Modern Browsers */\n url('./files/roboto-latin-700italic.woff') format('woff'); /* Modern Browsers */\n}\n\n/* roboto-900normal - latin */\n@font-face {\n font-family: 'Roboto';\n font-style: normal;\n font-display: swap;\n font-weight: 900;\n src:\n local('Roboto Black '),\n local('Roboto-Black'),\n url('./files/roboto-latin-900.woff2') format('woff2'), /* Super Modern Browsers */\n url('./files/roboto-latin-900.woff') format('woff'); /* Modern Browsers */\n}\n\n/* roboto-900italic - latin */\n@font-face {\n font-family: 'Roboto';\n font-style: italic;\n font-display: swap;\n font-weight: 900;\n src:\n local('Roboto Black italic'),\n local('Roboto-Blackitalic'),\n url('./files/roboto-latin-900italic.woff2') format('woff2'), /* Super Modern Browsers */\n url('./files/roboto-latin-900italic.woff') format('woff'); /* Modern Browsers */\n}\n\n"]}