@nyris/nyris-webapp 0.3.9 → 0.3.14

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 (32) hide show
  1. package/build/asset-manifest.json +11 -11
  2. package/build/index.html +1 -1
  3. package/build/js/settings.example.js +30 -0
  4. package/build/{precache-manifest.a97813497ab8d37548141e5e2618d0dc.js → precache-manifest.fa9930c6ba4e9fb0ebad3869127ef308.js} +9 -9
  5. package/build/service-worker.js +1 -1
  6. package/build/static/css/main.6633770c.chunk.css +2 -0
  7. package/build/static/css/main.6633770c.chunk.css.map +1 -0
  8. package/build/static/js/2.0798bb8b.chunk.js +3 -0
  9. package/build/static/js/{2.6e13adbe.chunk.js.LICENSE.txt → 2.0798bb8b.chunk.js.LICENSE.txt} +0 -0
  10. package/build/static/js/2.0798bb8b.chunk.js.map +1 -0
  11. package/build/static/js/main.31212715.chunk.js +2 -0
  12. package/build/static/js/main.31212715.chunk.js.map +1 -0
  13. package/package.json +2 -2
  14. package/public/js/settings.example.js +30 -0
  15. package/src/App.tsx +221 -203
  16. package/src/actions/nyrisAppActions.ts +69 -65
  17. package/src/actions/searchActions.ts +288 -196
  18. package/src/components/FiltersList.tsx +106 -57
  19. package/src/components/Header.tsx +29 -17
  20. package/src/components/SelectedFiltersSummary.tsx +84 -0
  21. package/src/components/Sidebar.tsx +41 -34
  22. package/src/epics/index.ts +128 -108
  23. package/src/epics/search.ts +114 -82
  24. package/src/index.css +95 -6
  25. package/src/index.tsx +89 -95
  26. package/src/utils.ts +5 -0
  27. package/build/static/css/main.0481043c.chunk.css +0 -2
  28. package/build/static/css/main.0481043c.chunk.css.map +0 -1
  29. package/build/static/js/2.6e13adbe.chunk.js +0 -3
  30. package/build/static/js/2.6e13adbe.chunk.js.map +0 -1
  31. package/build/static/js/main.f5da7aa4.chunk.js +0 -2
  32. package/build/static/js/main.f5da7aa4.chunk.js.map +0 -1
@@ -1,20 +1,32 @@
1
1
  import React from "react";
2
2
 
3
- const Header = () =>{
4
- return (
3
+ const Header = () => {
4
+ return (
5
5
  <div id="header">
6
-
7
- <section id="branding"></section>
8
- <div id="menu" className="menuWrap" role="navigation" >
9
- <ul>
10
- <li><a href="https://nyris.io/imprint/#privacy" target="_blank"
11
- rel="noopener noreferrer">Privacy Policy</a></li>
12
- <li><a href="https://nyris.io/" target="_blank" rel="noopener noreferrer">Visit our
13
- Website</a></li>
14
- </ul>
15
- </div>
16
- </div>
17
- );
18
-
19
- }
20
- export default Header;
6
+ <section id="branding"></section>
7
+ <div id="menu" className="menuWrap" role="navigation">
8
+ <ul>
9
+ <li>
10
+ <a
11
+ href="https://nyris.io/imprint/#privacy"
12
+ target="_blank"
13
+ rel="noopener noreferrer"
14
+ >
15
+ Privacy Policy
16
+ </a>
17
+ </li>
18
+ <li>
19
+ <a
20
+ href="https://nyris.io/"
21
+ target="_blank"
22
+ rel="noopener noreferrer"
23
+ >
24
+ Visit our Website
25
+ </a>
26
+ </li>
27
+ </ul>
28
+ </div>
29
+ </div>
30
+ );
31
+ };
32
+ export default Header;
@@ -0,0 +1,84 @@
1
+ import React from "react";
2
+ import { BsX } from "react-icons/bs";
3
+ import { connect, ConnectedProps, useDispatch } from "react-redux";
4
+ import { AppState } from "../types";
5
+ import { capitalizeFirstLetter } from "../utils";
6
+ import {
7
+ removeFromSelectedFilters,
8
+ clearAllSelectedFilters,
9
+ filterChanged,
10
+ } from "../actions/searchActions";
11
+
12
+ const SelectedFiltersSummary: React.FC<selectedFiltersSummaryProps> = ({
13
+ search,
14
+ }) => {
15
+ const dispatch = useDispatch();
16
+ const handleRemoveFilterButtonClick = (key: string, value: string) => {
17
+ dispatch(removeFromSelectedFilters(key, value));
18
+ dispatch(filterChanged());
19
+ };
20
+
21
+ const clearAllSelectedFiltersFromList = () => {
22
+ dispatch(clearAllSelectedFilters());
23
+ dispatch(filterChanged());
24
+ };
25
+ const selectedValues = ([] as string[]).concat.apply(
26
+ [],
27
+ Array.from(search.selectedFilters.values())
28
+ );
29
+
30
+ return (
31
+ <div className="wrap-box-refinements">
32
+ <ul>
33
+ {Array.from(search.selectedFilters.keys()).map(
34
+ (filterKey) =>
35
+ search.selectedFilters.get(filterKey) &&
36
+ search.selectedFilters.get(filterKey)!.map((val) => {
37
+ return (
38
+ <li>
39
+ <button
40
+ onClick={() =>
41
+ handleRemoveFilterButtonClick(filterKey, val)
42
+ }
43
+ >
44
+ <span className="summary-label">
45
+ <div className="summary-label-key-text">
46
+ {capitalizeFirstLetter(val)}
47
+ <BsX />
48
+ </div>
49
+ </span>
50
+ </button>
51
+ </li>
52
+ );
53
+ })
54
+ )}
55
+ <li>
56
+ <button
57
+ className={
58
+ search.selectedFilters &&
59
+ search.selectedFilters.size > 0 &&
60
+ selectedValues &&
61
+ selectedValues.length > 0
62
+ ? "clear-all-filters "
63
+ : "clear-all-filters-hidden"
64
+ }
65
+ onClick={() => clearAllSelectedFiltersFromList()}
66
+ >
67
+ Clear All
68
+ </button>
69
+ </li>
70
+ </ul>
71
+ </div>
72
+ );
73
+ };
74
+
75
+ const mapStateToProps = (state: AppState) => ({
76
+ showPart: state.nyrisDesign.showPart,
77
+ search: {
78
+ filters: state.search.filters,
79
+ selectedFilters: state.search.selectedFilters,
80
+ },
81
+ });
82
+ const connector = connect(mapStateToProps);
83
+ type selectedFiltersSummaryProps = ConnectedProps<typeof connector>;
84
+ export default connect(mapStateToProps)(SelectedFiltersSummary);
@@ -1,42 +1,49 @@
1
- import React, { useState } from 'react';
2
- import {RiMenuLine} from 'react-icons/ri';
3
- import { Filter } from '../../../nyris-api/index';
4
- import FiltersList from './FiltersList';
1
+ import React, { useState } from "react";
2
+ import { RiMenuLine } from "react-icons/ri";
3
+ import { Filter } from "../../../nyris-api/index";
4
+ import FiltersList from "./FiltersList";
5
5
 
6
6
  interface SidebarProps {
7
- filters: Filter[],
8
- selectedFilters: Map<string, string[]>
7
+ filters: Filter[];
8
+ selectedFilters: Map<string, string[]>;
9
9
  }
10
10
 
11
- const Sidebar: React.FC<SidebarProps> = ({filters, selectedFilters}) =>{
11
+ const Sidebar: React.FC<SidebarProps> = ({ filters, selectedFilters }) => {
12
+ console.log(filters);
12
13
  const [isExpanded, setIsExpanded] = useState(false);
13
- const handleToggler =()=>{
14
- if(isExpanded){
15
- setIsExpanded(false);
16
- return;
17
- }
18
- setIsExpanded(true);
19
- }
14
+ const handleToggler = () => {
15
+ if (isExpanded) {
16
+ setIsExpanded(false);
17
+ return;
18
+ }
19
+ setIsExpanded(true);
20
+ };
20
21
  return (
21
-
22
- <div className={isExpanded ? "sidebar" : "Sidebar collapsed"}>
23
- <div className="sidebarContent" >
24
- <div className="sidebarHeader">
25
- <RiMenuLine className="sidebar-icon" onClick={handleToggler}/>
26
- <h1 className={isExpanded ? "sidebar-logo" : "sidebar-logo collapsedHide"}> Select Filters </h1>
27
- </div>
28
- <div className={isExpanded ? "Sidebar-items" : "Sidebar-items collapsedHide"}>
29
- {filters && filters.map((x) => {
30
- let selectedValues = x.key ? selectedFilters.get(x.key): undefined
31
- return <FiltersList filter={x} selectedValues={selectedValues}/>
32
- })
33
- }
34
- </div>
35
- </div>
22
+ <div className={isExpanded ? "sidebar" : "Sidebar collapsed"}>
23
+ <div
24
+ className={
25
+ isExpanded ? "sidebarContent" : "sidebarContent overflowHidden"
26
+ }
27
+ >
28
+ <div className="sidebarHeader">
29
+ <RiMenuLine className="sidebar-icon" onClick={handleToggler} />
30
+ </div>
31
+ <div
32
+ className={
33
+ isExpanded ? "Sidebar-items" : "Sidebar-items collapsedHide"
34
+ }
35
+ >
36
+ {filters &&
37
+ filters.map((x) => {
38
+ let selectedValues = x.key
39
+ ? selectedFilters.get(x.key)
40
+ : undefined;
41
+ return <FiltersList filter={x} selectedValues={selectedValues} />;
42
+ })}
43
+ </div>
36
44
  </div>
37
-
38
-
39
- )
40
- }
45
+ </div>
46
+ );
47
+ };
41
48
 
42
- export default Sidebar
49
+ export default Sidebar;
@@ -9,146 +9,166 @@ import {AppAction} from "../types";
9
9
  import {selectFirstCenteredRegion} from "@nyris/nyris-api";
10
10
 
11
11
 
12
-
13
12
  const historyEpic: EpicConf = (action$, state$, {history}) => action$.pipe(
14
- ofType('SHOW_RESULTS', 'SHOW_START'),
15
- withLatestFrom(state$),
16
- tap(([action, state]) => {
17
- let { type } = action;
18
- console.log("action");
19
- console.log(state.search.selectedFilters);
20
- // action to clear all filters
21
- if (type === 'SHOW_RESULTS' && history.location.pathname !== '/results') {
22
- history.push('/results');
23
- }
24
- if (type === 'SHOW_START' && history.location.pathname !== '/') {
25
-
26
- history.goBack();
27
- }
28
- }),
29
- ignoreElements()
13
+ ofType('SHOW_RESULTS', 'SHOW_START'),
14
+ tap((action) => {
15
+ let { type } = action;
16
+ if (type === 'SHOW_RESULTS' && history.location.pathname !== '/results') {
17
+ history.push('/results');
18
+ }
19
+ if (type === 'SHOW_START' && history.location.pathname !== '/') {
20
+ history.goBack();
21
+ }
22
+ }),
23
+ ignoreElements()
30
24
  );
31
25
 
32
26
  const onSearchSuccessShowResults: EpicConf = (action$) => action$.pipe(
33
- ofType('SEARCH_REQUEST_SUCCEED'),
34
- map(showResults)
27
+ ofType('SEARCH_REQUEST_SUCCEED'),
28
+ map(showResults)
35
29
  );
36
30
 
37
31
  const onSearchSuccessRedirectToSite: EpicConf = (action$, state$) => action$.pipe(
38
- ofType('SEARCH_REQUEST_SUCCEED'),
39
- withLatestFrom(state$),
40
- tap(([action, {settings}]) => {
41
- if (action.type !== 'SEARCH_REQUEST_SUCCEED' || !action.results || action.results.length !== 1) {
42
- return;
43
- }
44
-
45
- const firstLink = action.results[0].l;
46
- const instantRedirectPatterns = settings.instantRedirectPatterns;
47
- if (!instantRedirectPatterns.find(r => new RegExp(r).test(firstLink))) {
48
- return;
49
- }
50
- window.location.href = firstLink;
51
- }),
52
- ignoreElements()
32
+ ofType('SEARCH_REQUEST_SUCCEED'),
33
+ withLatestFrom(state$),
34
+ tap(([action, {settings}]) => {
35
+ if (action.type !== 'SEARCH_REQUEST_SUCCEED' || !action.results || action.results.length !== 1) {
36
+ return;
37
+ }
38
+
39
+ const firstLink = action.results[0].l;
40
+ const instantRedirectPatterns = settings.instantRedirectPatterns;
41
+ if (!instantRedirectPatterns.find(r => new RegExp(r).test(firstLink))) {
42
+ return;
43
+ }
44
+ window.location.href = firstLink;
45
+ }),
46
+ ignoreElements()
53
47
  );
54
48
 
55
49
  const onSearchSuccessShowFeedbackDelayed: EpicConf = (action$) => action$.pipe(
56
- ofType('SEARCH_REQUEST_SUCCEED'),
57
- delay(3000),
58
- map(showFeedback)
50
+ ofType('SEARCH_REQUEST_SUCCEED'),
51
+ delay(3000),
52
+ map(showFeedback)
59
53
  );
60
54
 
61
55
 
62
56
  const startSearchOnImageLoaded: EpicConf = (action$, state$) => action$.pipe(
63
- ofType('IMAGE_LOADED'),
64
- withLatestFrom(state$),
65
- switchMap(async ([action, {settings}]) : Promise<AppAction> => {
66
- if (action.type !== 'IMAGE_LOADED') {
67
- throw new Error(`Wrong action type ${action.type}`);
68
- }
69
-
70
- let { image } = action;
71
-
72
- if (settings.regions) {
73
- return searchRegions(image.canvas);
74
- }
75
- return searchOffersForImage(image.canvas);
76
- })
57
+ ofType('IMAGE_LOADED'),
58
+ withLatestFrom(state$),
59
+ switchMap(async ([action, {settings}]) : Promise<AppAction> => {
60
+ if (action.type !== 'IMAGE_LOADED') {
61
+ throw new Error(`Wrong action type ${action.type}`);
62
+ }
63
+
64
+ let { image } = action;
65
+
66
+ if (settings.regions) {
67
+ return searchRegions(image.canvas);
68
+ }
69
+ return searchOffersForImage(image.canvas);
70
+ })
77
71
  );
78
72
 
79
73
  const startSearchOnCadLoaded: EpicConf = (action$, state$) => action$.pipe(
80
- ofType('CAD_LOADED'),
81
- withLatestFrom(state$),
82
- switchMap(async ([action, {settings}]) : Promise<AppAction> => {
83
- if (action.type !== 'CAD_LOADED') {
84
- throw new Error(`Wrong action type ${action.type}`);
85
- }
86
- let { file } = action;
87
- return searchOffersForCad(file);
88
- })
74
+ ofType('CAD_LOADED'),
75
+ withLatestFrom(state$),
76
+ switchMap(async ([action, {settings}]) : Promise<AppAction> => {
77
+ if (action.type !== 'CAD_LOADED') {
78
+ throw new Error(`Wrong action type ${action.type}`);
79
+ }
80
+ let { file } = action;
81
+ return searchOffersForCad(file);
82
+ })
89
83
  );
90
84
 
91
85
  const startSearchOnRegionsSuccessful: EpicConf = (action$, state$) => action$.pipe(
92
- ofType('REGION_REQUEST_SUCCEED'),
93
- withLatestFrom(state$),
94
- switchMap(async ([action, { search: { requestImage}}]) : Promise<AppAction> => {
95
- if (action.type !== 'REGION_REQUEST_SUCCEED') {
96
- throw new Error(`Wrong action type ${action.type}`);
97
- }
98
- if (!requestImage) {
99
- throw new Error(`No requestImage`);
100
- }
101
- let { regions } = action;
102
-
103
- let selection = selectFirstCenteredRegion(regions, 0.3, {x1: 0, x2: 1, y1: 0, y2: 1});
104
- return searchOffersForImage(requestImage.canvas, selection);
105
- })
86
+ ofType('REGION_REQUEST_SUCCEED'),
87
+ withLatestFrom(state$),
88
+ switchMap(async ([action, { search: { requestImage}}]) : Promise<AppAction> => {
89
+ if (action.type !== 'REGION_REQUEST_SUCCEED') {
90
+ throw new Error(`Wrong action type ${action.type}`);
91
+ }
92
+ if (!requestImage) {
93
+ throw new Error(`No requestImage`);
94
+ }
95
+ let { regions } = action;
96
+
97
+ let selection = selectFirstCenteredRegion(regions, 0.3, {x1: 0, x2: 1, y1: 0, y2: 1});
98
+ return searchOffersForImage(requestImage.canvas, selection);
99
+ })
106
100
  );
107
101
 
108
102
  const startSearchOnRegionsFailed: EpicConf = (action$, state$) => action$.pipe(
109
- ofType('REGION_REQUEST_FAIL'),
110
- withLatestFrom(state$),
111
- switchMap(async ([action, { search: { requestImage}}]) : Promise<AppAction> => {
112
- if (action.type !== 'REGION_REQUEST_FAIL') {
113
- throw new Error(`Wrong action type ${action.type}`);
114
- }
115
- if (!requestImage) {
116
- throw new Error(`No requestImage`);
117
- }
118
-
119
- return searchOffersForImage(requestImage.canvas);
120
- })
103
+ ofType('REGION_REQUEST_FAIL'),
104
+ withLatestFrom(state$),
105
+ switchMap(async ([action, { search: { requestImage}}]) : Promise<AppAction> => {
106
+ if (action.type !== 'REGION_REQUEST_FAIL') {
107
+ throw new Error(`Wrong action type ${action.type}`);
108
+ }
109
+ if (!requestImage) {
110
+ throw new Error(`No requestImage`);
111
+ }
112
+
113
+ return searchOffersForImage(requestImage.canvas);
114
+ })
121
115
  );
122
116
 
123
117
  const startSearchOnRegionChange: EpicConf = (action$, state$) => action$.pipe(
124
- ofType('REGION_CHANGED'),
125
- debounceTime(1200),
118
+ ofType('REGION_CHANGED'),
119
+ debounceTime(1200),
120
+ withLatestFrom(state$),
121
+ switchMap(async ([action, { search: { requestImage}}]) : Promise<AppAction> => {
122
+ if (action.type !== 'REGION_CHANGED') {
123
+ throw new Error(`Wrong action type ${action.type}`);
124
+ }
125
+ if (!requestImage) {
126
+ throw new Error(`No requestImage`);
127
+ }
128
+ let { normalizedRect } = action;
129
+ return searchOffersForImage(requestImage.canvas, normalizedRect);
130
+ })
131
+ );
132
+
133
+
134
+ const startSearchOnFilterChange: EpicConf = (action$, state$) =>
135
+ action$.pipe(
136
+ ofType("FILTER_CHANGED"),
126
137
  withLatestFrom(state$),
127
- switchMap(async ([action, { search: { requestImage}}]) : Promise<AppAction> => {
128
- if (action.type !== 'REGION_CHANGED') {
129
- throw new Error(`Wrong action type ${action.type}`);
138
+ switchMap(
139
+ async ([
140
+ action,
141
+ {
142
+ search: { requestImage },
143
+ },
144
+ ]): Promise<AppAction> => {
145
+ if (action.type !== "FILTER_CHANGED") {
146
+ throw new Error(`Wrong action type ${action.type}`);
130
147
  }
131
- if (!requestImage) {
132
- throw new Error(`No requestImage`);
148
+ if (requestImage) {
149
+ return searchOffersForImage(requestImage.canvas);
150
+ } else {
151
+ return { type: "FILTER_CHANGED_FAIL" };
133
152
  }
134
- let { normalizedRect } = action;
135
- return searchOffersForImage(requestImage.canvas, normalizedRect);
136
- })
137
- );
153
+ }
154
+ )
155
+ );
138
156
 
157
+ //const startSearchOnClearingAllFilters:
139
158
 
140
159
  const rootEpic = combineEpics(
141
- searchEpics,
142
- feedbackEpics,
143
- historyEpic,
144
- startSearchOnImageLoaded,
145
- startSearchOnCadLoaded,
146
- startSearchOnRegionsSuccessful,
147
- startSearchOnRegionsFailed,
148
- startSearchOnRegionChange,
149
- onSearchSuccessShowResults,
150
- onSearchSuccessShowFeedbackDelayed,
151
- onSearchSuccessRedirectToSite
160
+ searchEpics,
161
+ feedbackEpics,
162
+ historyEpic,
163
+ startSearchOnImageLoaded,
164
+ startSearchOnCadLoaded,
165
+ startSearchOnRegionsSuccessful,
166
+ startSearchOnRegionsFailed,
167
+ startSearchOnRegionChange,
168
+ onSearchSuccessShowResults,
169
+ onSearchSuccessShowFeedbackDelayed,
170
+ onSearchSuccessRedirectToSite,
171
+ startSearchOnFilterChange
152
172
  );
153
173
 
154
174
  export default rootEpic;