@nyris/nyris-webapp 0.3.6 → 0.3.13

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 (37) hide show
  1. package/build/asset-manifest.json +11 -11
  2. package/build/index.html +1 -1
  3. package/build/{precache-manifest.bffed513ca17d8ac16af1cc3aaa7d908.js → precache-manifest.793f0a4375602ec8cd0fba83bf0e3e67.js} +9 -9
  4. package/build/service-worker.js +1 -1
  5. package/build/static/css/main.0c9239ba.chunk.css +2 -0
  6. package/build/static/css/main.0c9239ba.chunk.css.map +1 -0
  7. package/build/static/js/2.520bb6d6.chunk.js +3 -0
  8. package/build/static/js/{2.4e9a4ce1.chunk.js.LICENSE.txt → 2.520bb6d6.chunk.js.LICENSE.txt} +0 -0
  9. package/build/static/js/2.520bb6d6.chunk.js.map +1 -0
  10. package/build/static/js/main.8405239a.chunk.js +2 -0
  11. package/build/static/js/main.8405239a.chunk.js.map +1 -0
  12. package/package.json +2 -2
  13. package/src/App.tsx +346 -213
  14. package/src/actions/nyrisAppActions.ts +69 -65
  15. package/src/actions/searchActions.ts +301 -196
  16. package/src/components/CategoryFilter.tsx +16 -13
  17. package/src/components/Codes.tsx +20 -16
  18. package/src/components/ExampleImages.tsx +27 -17
  19. package/src/components/Feedback.tsx +78 -48
  20. package/src/components/FiltersList.tsx +106 -59
  21. package/src/components/Header.tsx +29 -17
  22. package/src/components/PredictedCategories.tsx +15 -12
  23. package/src/components/Result.tsx +186 -113
  24. package/src/components/SelectedFiltersSummary.tsx +84 -0
  25. package/src/components/Sidebar.tsx +41 -32
  26. package/src/epics/index.ts +173 -104
  27. package/src/epics/search.ts +209 -177
  28. package/src/index.css +98 -9
  29. package/src/index.tsx +148 -144
  30. package/src/utils.ts +5 -0
  31. package/build/static/css/main.2a76dc8a.chunk.css +0 -2
  32. package/build/static/css/main.2a76dc8a.chunk.css.map +0 -1
  33. package/build/static/js/2.4e9a4ce1.chunk.js +0 -3
  34. package/build/static/js/2.4e9a4ce1.chunk.js.map +0 -1
  35. package/build/static/js/main.ec93aa4d.chunk.js +0 -2
  36. package/build/static/js/main.ec93aa4d.chunk.js.map +0 -1
  37. package/src/Demo2.tsx +0 -220
@@ -1,203 +1,235 @@
1
- import {EpicConf} from "./types";
2
- import {combineEpics, ofType} from "redux-observable";
3
- import {switchMap, withLatestFrom} from "rxjs/operators";
4
- import {AppAction} from "../types";
5
- import {ImageSearchOptions, urlOrBlobToCanvas, isCadFile, isImageFile, Filter } from "@nyris/nyris-api";
6
- import {imageLoaded, cadFileLoaded} from "../actions/searchActions";
7
-
8
- const imageSearch: EpicConf = (action$, state$, {api}) => action$.pipe(
9
- ofType('SEARCH_REQUEST_START'),
1
+ import { EpicConf } from "./types";
2
+ import { combineEpics, ofType } from "redux-observable";
3
+ import { switchMap, withLatestFrom } from "rxjs/operators";
4
+ import { AppAction } from "../types";
5
+ import {
6
+ ImageSearchOptions,
7
+ urlOrBlobToCanvas,
8
+ isCadFile,
9
+ isImageFile,
10
+ Filter,
11
+ } from "@nyris/nyris-api";
12
+ import { imageLoaded, cadFileLoaded } from "../actions/searchActions";
13
+
14
+ const imageSearch: EpicConf = (action$, state$, { api }) =>
15
+ action$.pipe(
16
+ ofType("SEARCH_REQUEST_START"),
10
17
  withLatestFrom(state$),
11
- switchMap(async ([action, state]) : Promise<AppAction> => {
12
- if (action.type !== 'SEARCH_REQUEST_START') {
13
- throw new Error(`Wrong action type ${action.type}`);
14
- }
15
- console.log("state search ");
16
- console.log(state.search.selectedFilters);
17
-
18
- if ('image' in action) {
19
- let { image, normalizedRect} = action;
20
- console.log("Selected Filters");
21
- let selectedFilters = new Array<Filter>();
22
- if(state.search.selectedFilters.size > 0 ){
23
- state.search.selectedFilters.forEach((values, key) => {
24
- let filterObj: Filter ={
25
- key : key,
26
- values : values
27
- }
28
- selectedFilters.push(filterObj);
29
- });
30
- }
31
-
32
- let options : ImageSearchOptions = {
33
- cropRect: normalizedRect
34
- };
35
-
36
- try {
37
- if(selectedFilters && selectedFilters.length> 0)
38
- {
39
- console.log("With Filters");
40
- const {results, duration, requestId, categoryPredictions, codes} = await api.findByImageWithFilters(image, options, selectedFilters);
41
- return ({ type: 'SEARCH_REQUEST_SUCCEED', results, requestId, duration, categoryPredictions, codes });
42
-
43
- }
44
- else{
45
- console.log("Without Filters");
46
- const {results, duration, requestId, categoryPredictions, codes} = await api.findByImage(image, options);
47
- return ({ type: 'SEARCH_REQUEST_SUCCEED', results, requestId, duration, categoryPredictions, codes });
48
- }
49
- } catch (e) {
50
- console.warn('search failed', e);
51
- return ({ type: 'SEARCH_REQUEST_FAIL', reason: e.message, exception: e });
18
+ switchMap(async ([action, state]): Promise<AppAction> => {
19
+ if (action.type !== "SEARCH_REQUEST_START") {
20
+ throw new Error(`Wrong action type ${action.type}`);
21
+ }
22
+ if ("image" in action) {
23
+ let { image, normalizedRect } = action;
24
+
25
+ // refactor this
26
+ let selectedFilters = new Array<Filter>();
27
+ if (state.search.selectedFilters.size > 0) {
28
+ state.search.selectedFilters.forEach((values, key) => {
29
+ if (values && values.length > 0) {
30
+ let filterObj: Filter = {
31
+ key: key,
32
+ values: values,
33
+ };
34
+ selectedFilters.push(filterObj);
52
35
  }
36
+ });
53
37
  }
54
38
 
55
- if ('file' in action) {
56
- console.log('file');
57
- let { file } = action;
39
+ let options: ImageSearchOptions = {
40
+ cropRect: normalizedRect,
41
+ };
58
42
 
59
- let options : ImageSearchOptions = { };
60
-
61
- try {
62
- const {results, duration, requestId, categoryPredictions, codes} = await api.findByCad(file, options);
63
- return ({ type: 'SEARCH_REQUEST_SUCCEED', results, requestId, duration, categoryPredictions, codes });
64
- } catch (e) {
65
- console.warn('search failed', e);
66
- return ({ type: 'SEARCH_REQUEST_FAIL', reason: e.message, exception: e });
67
- }
43
+ try {
44
+ if (selectedFilters && selectedFilters.length > 0) {
45
+ console.log("With Filters");
46
+ const { results, duration, requestId, categoryPredictions, codes } =
47
+ await api.findByImageWithFilters(image, options, selectedFilters);
48
+ return {
49
+ type: "SEARCH_REQUEST_SUCCEED",
50
+ results,
51
+ requestId,
52
+ duration,
53
+ categoryPredictions,
54
+ codes,
55
+ };
56
+ } else {
57
+ console.log("Without Filters");
58
+ const { results, duration, requestId, categoryPredictions, codes } =
59
+ await api.findByImage(image, options);
60
+ return {
61
+ type: "SEARCH_REQUEST_SUCCEED",
62
+ results,
63
+ requestId,
64
+ duration,
65
+ categoryPredictions,
66
+ codes,
67
+ };
68
+ }
69
+ } catch (e) {
70
+ console.warn("search failed", e);
71
+ return {
72
+ type: "SEARCH_REQUEST_FAIL",
73
+ reason: e.message,
74
+ exception: e,
75
+ };
68
76
  }
69
- throw new Error(`Wrong action content ${action}`);
70
- })
71
- );
77
+ }
72
78
 
73
- const regionSearch: EpicConf = (action$, state$, {api}) => action$.pipe(
74
- ofType('REGION_REQUEST_START'),
75
- withLatestFrom(state$),
76
- switchMap(async ([action, {settings}]) : Promise<AppAction> => {
77
- if (action.type !== 'REGION_REQUEST_START') {
78
- throw new Error(`Wrong action type ${action.type}`);
79
- }
79
+ if ("file" in action) {
80
+ console.log("file");
81
+ let { file } = action;
80
82
 
81
- let { image } = action;
83
+ let options: ImageSearchOptions = {};
82
84
 
83
85
  try {
84
- let regions = await api.findRegions(image);
85
- return {type: 'REGION_REQUEST_SUCCEED', regions };
86
-
86
+ const { results, duration, requestId, categoryPredictions, codes } =
87
+ await api.findByCad(file, options);
88
+ return {
89
+ type: "SEARCH_REQUEST_SUCCEED",
90
+ results,
91
+ requestId,
92
+ duration,
93
+ categoryPredictions,
94
+ codes,
95
+ };
87
96
  } catch (e) {
88
- console.error(e);
89
- return {type: 'REGION_REQUEST_FAIL', reason: e.message, exception: e};
97
+ console.warn("search failed", e);
98
+ return {
99
+ type: "SEARCH_REQUEST_FAIL",
100
+ reason: e.message,
101
+ exception: e,
102
+ };
90
103
  }
104
+ }
105
+ throw new Error(`Wrong action content ${action}`);
91
106
  })
92
- );
107
+ );
93
108
 
94
- const loadFile: EpicConf = (action$) => action$.pipe(
95
- ofType('LOAD_FILE'),
96
- switchMap(async (action) : Promise<AppAction> => {
97
- if (action.type !== 'LOAD_FILE') {
98
- throw new Error(`Wrong action type ${action.type}`);
99
- }
100
- const randomId = Math.random().toString();
101
- if ('file' in action) {
102
- const file = action.file;
103
- if (isImageFile(file)) {
104
- return imageLoaded(await urlOrBlobToCanvas(file), randomId);
105
- }
106
- if (isCadFile(file)) {
107
- return cadFileLoaded(file, randomId);
108
- }
109
- }
110
- throw new Error(`LOAD_FILE action wrong properties ${Object.keys(action).join(',')}`);
109
+ const regionSearch: EpicConf = (action$, state$, { api }) =>
110
+ action$.pipe(
111
+ ofType("REGION_REQUEST_START"),
112
+ withLatestFrom(state$),
113
+ switchMap(async ([action, { settings }]): Promise<AppAction> => {
114
+ if (action.type !== "REGION_REQUEST_START") {
115
+ throw new Error(`Wrong action type ${action.type}`);
116
+ }
117
+
118
+ let { image } = action;
119
+
120
+ try {
121
+ let regions = await api.findRegions(image);
122
+ return { type: "REGION_REQUEST_SUCCEED", regions };
123
+ } catch (e) {
124
+ console.error(e);
125
+ return { type: "REGION_REQUEST_FAIL", reason: e.message, exception: e };
126
+ }
111
127
  })
112
- );
113
-
114
- const loadImage: EpicConf = (action$) => action$.pipe(
115
- ofType('LOAD_IMAGE'),
116
- switchMap(async (action) : Promise<AppAction> => {
117
- if (action.type !== 'LOAD_IMAGE') {
118
- throw new Error(`Wrong action type ${action.type}`);
119
- }
120
- const randomId = Math.random().toString();
121
- if ('url' in action) {
122
- return imageLoaded(await urlOrBlobToCanvas(action.url), randomId);
123
- }
124
- if ('file' in action) {
125
- return imageLoaded(await urlOrBlobToCanvas(action.file), randomId);
128
+ );
129
+
130
+ const loadFile: EpicConf = (action$) =>
131
+ action$.pipe(
132
+ ofType("LOAD_FILE"),
133
+ switchMap(async (action): Promise<AppAction> => {
134
+ if (action.type !== "LOAD_FILE") {
135
+ throw new Error(`Wrong action type ${action.type}`);
136
+ }
137
+ const randomId = Math.random().toString();
138
+ if ("file" in action) {
139
+ const file = action.file;
140
+ if (isImageFile(file)) {
141
+ return imageLoaded(await urlOrBlobToCanvas(file), randomId);
126
142
  }
127
- if ('image' in action) {
128
- return imageLoaded(action.image, randomId);
143
+ if (isCadFile(file)) {
144
+ return cadFileLoaded(file, randomId);
129
145
  }
130
- throw new Error(`LOAD_IMAGE action wrong properties ${Object.keys(action).join(',')}`);
146
+ }
147
+ throw new Error(
148
+ `LOAD_FILE action wrong properties ${Object.keys(action).join(",")}`
149
+ );
131
150
  })
132
- );
133
-
151
+ );
152
+
153
+ const loadImage: EpicConf = (action$) =>
154
+ action$.pipe(
155
+ ofType("LOAD_IMAGE"),
156
+ switchMap(async (action): Promise<AppAction> => {
157
+ if (action.type !== "LOAD_IMAGE") {
158
+ throw new Error(`Wrong action type ${action.type}`);
159
+ }
160
+ const randomId = Math.random().toString();
161
+ if ("url" in action) {
162
+ return imageLoaded(await urlOrBlobToCanvas(action.url), randomId);
163
+ }
164
+ if ("file" in action) {
165
+ return imageLoaded(await urlOrBlobToCanvas(action.file), randomId);
166
+ }
167
+ if ("image" in action) {
168
+ return imageLoaded(action.image, randomId);
169
+ }
170
+ throw new Error(
171
+ `LOAD_IMAGE action wrong properties ${Object.keys(action).join(",")}`
172
+ );
173
+ })
174
+ );
134
175
 
135
- const loadFilters: EpicConf = (action$, state$, {api}) => action$.pipe(
136
- ofType('LOAD_FILTERS'),
176
+ const loadFilters: EpicConf = (action$, state$, { api }) =>
177
+ action$.pipe(
178
+ ofType("LOAD_FILTERS"),
137
179
  withLatestFrom(state$),
138
- switchMap(async ([action, state]) : Promise<AppAction> => {
139
- if(action.type !== 'LOAD_FILTERS'){
140
- throw new Error(`Wrong action type ${action.type}`);
141
- }
142
- try {
143
- // use find filters
144
-
145
- let filters = await api.getFilters();
146
-
147
- filters= filters.slice(0, 3);
148
- console.log(filters);
149
- // let filters : Filter[] = [
150
- // {
151
- // filterType: 'MachineType',
152
- // filterValues : [
153
- // "MachineType1",
154
- // "MachineType2",
155
- // "MachineType3",
156
- // "MachineType4",
157
- // "MachineType5"
158
- // ]
159
- // },
160
- // {
161
- // filterType: 'Color',
162
- // filterValues :[
163
- // "Red",
164
- // "Green",
165
- // "Blue",
166
- // "Yellow",
167
- // "Black"
168
- // ]
169
- // }];
170
- return {type: 'LOAD_FILTERS_SUCCESS', filters };
171
-
172
- } catch (e) {
173
- console.error(e);
174
- return {type: 'LOAD_FILTERS_FAIL', reason: e.message, exception: e};
175
- }
180
+ switchMap(async ([action, state]): Promise<AppAction> => {
181
+ if (action.type !== "LOAD_FILTERS") {
182
+ throw new Error(`Wrong action type ${action.type}`);
183
+ }
184
+ try {
185
+ // use find filters
186
+
187
+ let filters = await api.getFilters();
188
+ return { type: "LOAD_FILTERS_SUCCESS", filters };
189
+ } catch (e) {
190
+ console.error(e);
191
+ return { type: "LOAD_FILTERS_FAIL", reason: e.message, exception: e };
192
+ }
176
193
  })
177
- );
194
+ );
178
195
 
179
- const addToSelectedFilters: EpicConf = (action$) => action$.pipe(
180
- ofType('ADD_TO_SELECTEDFILTERS'),
181
- switchMap(async (action) : Promise<AppAction> => {
182
-
183
- if(action.type !== 'ADD_TO_SELECTEDFILTERS'){
184
- throw new Error(`Wrong action type ${action.type}`);
196
+ const searchFilters: EpicConf = (action$, state$, { api }) =>
197
+ action$.pipe(
198
+ ofType("SEARCH_FILTERS"),
199
+ withLatestFrom(state$),
200
+ switchMap(async ([action, state]): Promise<AppAction> => {
201
+ if (action.type !== "SEARCH_FILTERS") {
202
+ throw new Error(`Wrong action type ${action.type}`);
203
+ }
204
+ try {
205
+ let { key, value } = action;
206
+ let values: string[] = [];
207
+ if (value) {
208
+ let response = await api.searchFilters(key, value);
209
+ if (response && response.length > 0) {
210
+ values = values.concat(await api.searchFilters(key, value));
211
+ }
212
+ } else {
213
+ // if no value load default values in search
214
+ let defaultfilters = await api.getFilters();
215
+ let filter = defaultfilters.find((x) => x.key === key);
216
+ if (filter && filter.values && filter.values.length > 0) {
217
+ values = filter.values;
218
+ }
185
219
  }
186
- if('key' in action && 'value' in action){
187
-
188
- let {key, value} = action;
189
- console.log(key);
190
- console.log(action);
191
- return {type : 'ADD_TO_SELECTEDFILTERS_SUCCESS', key , value }
192
- }
193
- throw new Error(`Change filters action wrong properties ${Object.keys(action).join(',')}`);
220
+ return { type: "UPDATE_FILTERS", key, values };
221
+ } catch (e) {
222
+ console.error(e);
223
+ return { type: "LOAD_FILTERS_FAIL", reason: e.message, exception: e };
224
+ }
194
225
  })
195
- );
226
+ );
196
227
 
197
228
  export default combineEpics(
198
- imageSearch,
199
- regionSearch,
200
- loadFile,
201
- loadImage,
202
- loadFilters,
203
- addToSelectedFilters);
229
+ imageSearch,
230
+ regionSearch,
231
+ loadFile,
232
+ loadImage,
233
+ loadFilters,
234
+ searchFilters
235
+ );
package/src/index.css CHANGED
@@ -315,7 +315,7 @@ h1, h2 {
315
315
 
316
316
  h1 {
317
317
  font-size: 25px;
318
- margin: 0 auto 25px
318
+ margin: 0 auto
319
319
  }
320
320
 
321
321
  h1.entry-title a {
@@ -553,7 +553,7 @@ a img.aligncenter {
553
553
  }
554
554
 
555
555
  .headSection {
556
- position: absolute;
556
+ position: relative;
557
557
  width: 100%;
558
558
  height: 90vh;
559
559
  height: -webkit-calc(100vh - 30px);
@@ -648,7 +648,6 @@ a img.aligncenter {
648
648
  -webkit-box-pack: center;
649
649
  -ms-flex-pack: center;
650
650
  justify-content: center;
651
- margin-left: 35px;
652
651
  margin-top: 50px;
653
652
  }
654
653
  .dragAndDropActionArea:focus {
@@ -1456,7 +1455,7 @@ a img.aligncenter {
1456
1455
  background: #031F2B;
1457
1456
 
1458
1457
  -ms-flex-pack: justify;
1459
- height: calc( 100vh - 60px);
1458
+ height: 100%;
1460
1459
  }
1461
1460
  .sidebar {
1462
1461
  order: 0;
@@ -1469,13 +1468,15 @@ a img.aligncenter {
1469
1468
  -webkit-flex: 0 0 329px;
1470
1469
  -ms-flex: 0 0 329px;
1471
1470
  flex: 0 0 240px;
1472
- border-right: 1px solid #eee;
1473
1471
  width: 25%;
1472
+ height:100%
1474
1473
  }
1475
1474
  .mainContent{
1476
1475
  width: calc(100vh-230);
1477
- flex: 0 0 900px;
1476
+ flex: 0 0 80%;
1478
1477
  flex-grow: 1;
1478
+ position: inherit;
1479
+ border-left: 1px solid #eee;
1479
1480
  }
1480
1481
  .sidebarContent {
1481
1482
  height: 100%;
@@ -1487,7 +1488,7 @@ a img.aligncenter {
1487
1488
  .sidebarHeader{
1488
1489
  display: flex;
1489
1490
  align-items: center;
1490
- padding: 16px;
1491
+ padding: 3px;
1491
1492
  }
1492
1493
  .sidebar-icon{
1493
1494
  width: 1.25em;
@@ -1502,8 +1503,11 @@ a img.aligncenter {
1502
1503
  font-size: 16px;
1503
1504
  float: left;
1504
1505
  color: white;
1505
- margin-top: 27px;
1506
+ margin-top: 7px;
1506
1507
  }
1508
+ .sidebarContent{
1509
+ overflow-y: auto;
1510
+ }
1507
1511
  .Sidebar-items{
1508
1512
  display: flex;
1509
1513
  flex-direction: column;
@@ -1535,11 +1539,96 @@ a img.aligncenter {
1535
1539
  }
1536
1540
  .sidebar-text{
1537
1541
  color: white;
1542
+ font-size: 16px;
1543
+ }
1544
+ .overflowHidden{
1545
+ overflow-y: hidden;
1538
1546
  }
1539
-
1540
1547
  .itemLabel{
1541
1548
  padding-left: 10px;
1549
+ font-size: 14px;
1550
+ max-width: 3ch;
1551
+ overflow: hidden;
1552
+ text-overflow: ellipsis;
1542
1553
  }
1554
+ .itemLabel:hover::before {
1555
+ content: attr(data-title);
1556
+ position: absolute;
1557
+ bottom: -46px;
1558
+ padding: 10px;
1559
+ background: #000;
1560
+ color: #fff;
1561
+ font-size: 14px;
1562
+ white-space: nowrap;
1563
+ }
1564
+ .itemLabel:hover::after {
1565
+ content: '';
1566
+ position: absolute;
1567
+ bottom: -12px;
1568
+ left: 8px;
1569
+ border: 8px solid transparent;
1570
+ border-bottom: 8px solid #000;
1571
+ }
1572
+
1573
+ #searchQueryInput {
1574
+ width: 100%;
1575
+ height: 1.8rem;
1576
+ background: #f5f5f5;
1577
+ outline: none;
1578
+ border: none;
1579
+ border-radius: 1.625rem;
1580
+ padding: 0 3.5rem 0 1.5rem;
1581
+ font-size: 1rem;
1582
+ }
1583
+
1584
+ #searchQuerySubmit {
1585
+ width: 3.5rem;
1586
+ height: 2.8rem;
1587
+ margin-left: -3.5rem;
1588
+ background: none;
1589
+ border: none;
1590
+ outline: none;
1591
+ }
1592
+
1593
+ .searchBar {
1594
+ width: 100%;
1595
+ display: flex;
1596
+ flex-direction: row;
1597
+ align-items: center;
1598
+ }
1599
+
1600
+ .wrap-box-refinements{
1601
+ width: 100%;
1602
+ margin-top: 16px;
1603
+ }
1604
+ .wrap-box-refinements ul{
1605
+ display: flex;
1606
+ flex-wrap: wrap;
1607
+ width: 100%;
1608
+ grid-gap: 8px;
1609
+ gap: 8px;
1610
+ align-items: center;
1611
+ }
1612
+ .summary-label{
1613
+ width: 100%;
1614
+ display: inherit;
1615
+ align-items: inherit;
1616
+ justify-content: inherit;
1617
+ }
1618
+
1619
+ .summary-label-key-text{
1620
+ font-size: 13px;
1621
+ }
1622
+
1623
+ .clear-all-filters-hidden{
1624
+ display: none;
1625
+ }
1626
+ .clear-all-filters{
1627
+ border: 0;
1628
+ background: initial;
1629
+ color: red;
1630
+ font-size: 13px;
1631
+ }
1543
1632
  #catlist a { display: inline-block; padding: 10px; border-radius: 10px; }
1544
1633
  #catlist a:hover { background-color: white; }
1545
1634
  #catlist a.selected { background-color: #444; color: #ddd; }