@nyris/nyris-webapp 0.3.69 → 0.3.70
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.
- package/.env +1 -0
- package/build/asset-manifest.json +7 -3
- package/build/index.html +1 -1
- package/build/js/settings.example.js +7 -0
- package/build/static/js/906.26c8485c.chunk.js +2 -0
- package/build/static/js/906.26c8485c.chunk.js.map +1 -0
- package/build/static/js/95.c359f13c.chunk.js +2 -0
- package/build/static/js/95.c359f13c.chunk.js.map +1 -0
- package/build/static/js/main.9ef0f70d.js +3 -0
- package/build/static/js/{main.bbe06da4.js.map → main.9ef0f70d.js.map} +1 -1
- package/package.json +6 -3
- package/public/js/settings.example.js +7 -0
- package/src/components/DragDropFile.tsx +1 -3
- package/src/components/ProductDetailView.tsx +93 -35
- package/src/components/UploadDisclaimer.tsx +3 -4
- package/src/components/drawer/cameraCustom.tsx +3 -5
- package/src/components/input/inputSearch.tsx +4 -2
- package/src/hooks/useImageSearch.ts +27 -4
- package/src/translations.ts +1 -1
- package/src/types.ts +6 -0
- package/build/static/js/main.bbe06da4.js +0 -3
- /package/build/static/js/{main.bbe06da4.js.LICENSE.txt → main.9ef0f70d.js.LICENSE.txt} +0 -0
package/package.json
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nyris/nyris-webapp",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.70",
|
|
4
4
|
"dependencies": {
|
|
5
5
|
"@auth0/auth0-react": "^2.2.4",
|
|
6
6
|
"@emailjs/browser": "^4.3.3",
|
|
7
7
|
"@material-ui/core": "^4.12.4",
|
|
8
8
|
"@material-ui/icons": "^4.11.3",
|
|
9
9
|
"@material-ui/lab": "^4.0.0-alpha.61",
|
|
10
|
-
"@nyris/nyris-api": "^0.3.
|
|
11
|
-
"@nyris/nyris-react-components": "^0.3.
|
|
10
|
+
"@nyris/nyris-api": "^0.3.70",
|
|
11
|
+
"@nyris/nyris-react-components": "^0.3.70",
|
|
12
12
|
"@reduxjs/toolkit": "^2.2.1",
|
|
13
13
|
"@splidejs/react-splide": "^0.7.12",
|
|
14
14
|
"@testing-library/jest-dom": "^5.17.0",
|
|
15
15
|
"@testing-library/react": "^13.4.0",
|
|
16
16
|
"@testing-library/user-event": "^13.5.0",
|
|
17
|
+
"@types/heic-convert": "^2.1.0",
|
|
17
18
|
"@types/jest": "^27.5.2",
|
|
18
19
|
"@types/node": "^16.18.88",
|
|
19
20
|
"@types/react": "^18.2.65",
|
|
@@ -23,7 +24,9 @@
|
|
|
23
24
|
"blueimp-load-image": "^5.16.0",
|
|
24
25
|
"classnames": "^2.5.1",
|
|
25
26
|
"compressorjs": "^1.2.1",
|
|
27
|
+
"env": "^0.0.2",
|
|
26
28
|
"framer-motion": "^11.0.12",
|
|
29
|
+
"heic-convert": "^2.1.0",
|
|
27
30
|
"i18next": "^23.10.1",
|
|
28
31
|
"jotai": "^1.4.7",
|
|
29
32
|
"jquery": "^3.7.1",
|
|
@@ -95,9 +95,7 @@ function DragDropFile(props: Props) {
|
|
|
95
95
|
className="inputFile"
|
|
96
96
|
placeholder="Choose photo"
|
|
97
97
|
style={{ display: 'block', cursor: 'pointer' }}
|
|
98
|
-
accept={
|
|
99
|
-
isCadSearch ? '.stp,.step,.stl,.obj,.glb,.gltf,' : ''
|
|
100
|
-
}image/*`}
|
|
98
|
+
accept={'.stp,.step,.stl,.obj,.glb,.gltf,.heic,.heif,image/*'}
|
|
101
99
|
/>
|
|
102
100
|
</div>
|
|
103
101
|
</div>
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import React, { useEffect,
|
|
2
|
-
import { Button,
|
|
1
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { Button, Grid, Typography, Tooltip } from '@material-ui/core';
|
|
3
3
|
import CloseOutlinedIcon from '@material-ui/icons/CloseOutlined';
|
|
4
|
-
import KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown';
|
|
5
4
|
import { Icon } from '@nyris/nyris-react-components';
|
|
6
5
|
import NoImage from '../common/assets/images/no-image.svg';
|
|
7
6
|
import { useMediaQuery } from 'react-responsive';
|
|
@@ -9,7 +8,6 @@ import { ImagePreviewCarousel } from './carousel/ImagePreviewCarousel';
|
|
|
9
8
|
import { AppState } from 'types';
|
|
10
9
|
import { useAppSelector } from 'Store/Store';
|
|
11
10
|
import { prepareImageList } from '../helpers/CommonHelper';
|
|
12
|
-
import KeyboardArrowUpIcon from '@material-ui/icons/KeyboardArrowUp';
|
|
13
11
|
import { useTranslation } from 'react-i18next';
|
|
14
12
|
import ProductAttribute from './ProductAttribute';
|
|
15
13
|
import CadenasWebViewer from './CadenasWebViewer';
|
|
@@ -56,6 +54,9 @@ function ProductDetailView(props: Props) {
|
|
|
56
54
|
>();
|
|
57
55
|
const { t } = useTranslation();
|
|
58
56
|
const classes = useStyles(props?.show3dView);
|
|
57
|
+
const modal = useRef<any>(null);
|
|
58
|
+
const extraDetailPropertyLength = isMobile ? 15 : 30;
|
|
59
|
+
const extraDetailValueLength = isMobile ? 35 : 60;
|
|
59
60
|
|
|
60
61
|
useEffect(() => {
|
|
61
62
|
if (dataItem) {
|
|
@@ -92,17 +93,10 @@ function ProductDetailView(props: Props) {
|
|
|
92
93
|
|
|
93
94
|
setDataImageCarouSel(valueKey);
|
|
94
95
|
};
|
|
95
|
-
const productDetails = useMemo(() => {
|
|
96
|
-
const details = get(dataItem, settings.productDetails);
|
|
97
|
-
try {
|
|
98
|
-
return details.join(', ');
|
|
99
|
-
} catch (e) {
|
|
100
|
-
return details;
|
|
101
|
-
}
|
|
102
|
-
}, [dataItem, settings.productDetails]);
|
|
103
96
|
|
|
104
97
|
return (
|
|
105
98
|
<div
|
|
99
|
+
ref={modal}
|
|
106
100
|
className="box-modal-default"
|
|
107
101
|
style={{
|
|
108
102
|
margin: isMobile ? 0 : '',
|
|
@@ -591,8 +585,8 @@ function ProductDetailView(props: Props) {
|
|
|
591
585
|
</div>
|
|
592
586
|
)}
|
|
593
587
|
</div>
|
|
594
|
-
|
|
595
|
-
{
|
|
588
|
+
|
|
589
|
+
{settings.productDetailsAttribute?.length ? (
|
|
596
590
|
<div className="w-100">
|
|
597
591
|
<Button
|
|
598
592
|
className="w-100 button-hover"
|
|
@@ -607,34 +601,98 @@ function ProductDetailView(props: Props) {
|
|
|
607
601
|
paddingRight: '15px',
|
|
608
602
|
textTransform: 'initial',
|
|
609
603
|
}}
|
|
610
|
-
onClick={() =>
|
|
604
|
+
onClick={(e) => {
|
|
605
|
+
setCollapseDescription(prev => !prev);
|
|
606
|
+
if (modal && modal.current) {
|
|
607
|
+
setTimeout(() => {
|
|
608
|
+
const top = (settings.productDetailsAttribute?.length || 0) * 30 + 20;
|
|
609
|
+
modal.current.parentElement.scrollTo({ top });
|
|
610
|
+
});
|
|
611
|
+
}
|
|
612
|
+
}}
|
|
611
613
|
>
|
|
612
614
|
{t('View details')}
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
/>
|
|
621
|
-
)}
|
|
615
|
+
<span
|
|
616
|
+
style={{
|
|
617
|
+
fontSize: 20,
|
|
618
|
+
}}
|
|
619
|
+
>
|
|
620
|
+
{collapseDescription ? '—' : '+'}
|
|
621
|
+
</span>
|
|
622
622
|
</Button>
|
|
623
|
-
|
|
624
|
-
<
|
|
623
|
+
{collapseDescription ? (
|
|
624
|
+
<div
|
|
625
625
|
style={{
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
626
|
+
background: '#E9E9EC',
|
|
627
|
+
borderRadius: 2,
|
|
628
|
+
display: 'flex',
|
|
629
|
+
flexDirection: 'column',
|
|
630
|
+
gap: 6,
|
|
631
|
+
padding: '6px 15px 10px',
|
|
631
632
|
}}
|
|
632
633
|
>
|
|
633
|
-
{
|
|
634
|
-
|
|
635
|
-
|
|
634
|
+
{settings.productDetailsAttribute.map((detail) =>
|
|
635
|
+
get(dataItem, detail.value)?.length
|
|
636
|
+
? (
|
|
637
|
+
<div
|
|
638
|
+
style={{
|
|
639
|
+
height: 14,
|
|
640
|
+
display: 'flex',
|
|
641
|
+
flexDirection: 'row',
|
|
642
|
+
alignItems: 'center'
|
|
643
|
+
}}
|
|
644
|
+
>
|
|
645
|
+
<Tooltip
|
|
646
|
+
title={detail.propertyName}
|
|
647
|
+
placement="top"
|
|
648
|
+
arrow={true}
|
|
649
|
+
disableHoverListener={detail.propertyName.length < extraDetailPropertyLength}
|
|
650
|
+
>
|
|
651
|
+
<span
|
|
652
|
+
style={{
|
|
653
|
+
fontFamily: 'Source Sans 3',
|
|
654
|
+
fontSize: 12,
|
|
655
|
+
fontWeight: 600,
|
|
656
|
+
marginRight: 8,
|
|
657
|
+
height: 14,
|
|
658
|
+
}}
|
|
659
|
+
>
|
|
660
|
+
{detail.propertyName.length < extraDetailPropertyLength
|
|
661
|
+
? detail.propertyName
|
|
662
|
+
: detail.propertyName.substring(0, extraDetailPropertyLength).concat('...')
|
|
663
|
+
}
|
|
664
|
+
</span>
|
|
665
|
+
</Tooltip>
|
|
666
|
+
<Tooltip
|
|
667
|
+
title={get(dataItem, detail.value)}
|
|
668
|
+
placement="top"
|
|
669
|
+
arrow={true}
|
|
670
|
+
disableHoverListener={get(dataItem, detail.value)?.length <= extraDetailValueLength}
|
|
671
|
+
>
|
|
672
|
+
<Typography
|
|
673
|
+
style={{
|
|
674
|
+
fontFamily: 'Source Sans 3',
|
|
675
|
+
fontSize: 12,
|
|
676
|
+
fontWeight: 400,
|
|
677
|
+
height: 14,
|
|
678
|
+
}}
|
|
679
|
+
>
|
|
680
|
+
{get(dataItem, detail.value).length <= extraDetailValueLength
|
|
681
|
+
? get(dataItem, detail.value)
|
|
682
|
+
: get(dataItem, detail.value).substring(0, extraDetailValueLength).concat('...')
|
|
683
|
+
}
|
|
684
|
+
</Typography>
|
|
685
|
+
</Tooltip>
|
|
686
|
+
</div>
|
|
687
|
+
)
|
|
688
|
+
: (
|
|
689
|
+
''
|
|
690
|
+
)
|
|
691
|
+
)}
|
|
692
|
+
</div>
|
|
693
|
+
) : ('')}
|
|
636
694
|
</div>
|
|
637
|
-
)}
|
|
695
|
+
) : ('')}
|
|
638
696
|
</Grid>
|
|
639
697
|
</Grid>
|
|
640
698
|
</div>
|
|
@@ -13,7 +13,6 @@ function UploadDisclaimer({
|
|
|
13
13
|
isMobile: boolean;
|
|
14
14
|
}) {
|
|
15
15
|
const [dontShowAgain, setDontShowAgain] = useState(false);
|
|
16
|
-
const isCadSearch = window.settings.cadSearch;
|
|
17
16
|
|
|
18
17
|
return (
|
|
19
18
|
<>
|
|
@@ -68,9 +67,9 @@ function UploadDisclaimer({
|
|
|
68
67
|
type="file"
|
|
69
68
|
name="take-picture"
|
|
70
69
|
id="nyris__upload-photo"
|
|
71
|
-
accept={
|
|
72
|
-
|
|
73
|
-
}
|
|
70
|
+
accept={
|
|
71
|
+
'.stp,.step,.stl,.obj,.glb,.gltf,.heic,.heif,image/jpeg,image/png,image/webp'
|
|
72
|
+
}
|
|
74
73
|
onChange={makeFileHandler(file =>
|
|
75
74
|
onContinue({ file, dontShowAgain }),
|
|
76
75
|
)}
|
|
@@ -257,11 +257,9 @@ function CameraCustom(props: Props) {
|
|
|
257
257
|
handlerFindImage(file);
|
|
258
258
|
}
|
|
259
259
|
}}
|
|
260
|
-
accept={
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
: ''
|
|
264
|
-
}image/jpeg,image/png,image/webp`}
|
|
260
|
+
accept={
|
|
261
|
+
'.stp,.step,.stl,.obj,.glb,.gltf,.heic,.heif,image/jpeg,image/png,image/webp'
|
|
262
|
+
}
|
|
265
263
|
onClick={event => {
|
|
266
264
|
// @ts-ignore
|
|
267
265
|
event.target.value = '';
|
|
@@ -322,8 +322,10 @@ const SearchBox = (props: any) => {
|
|
|
322
322
|
<div className="wrap-box-input-mobile d-flex">
|
|
323
323
|
<input
|
|
324
324
|
accept={`${
|
|
325
|
-
isCadSearch
|
|
326
|
-
|
|
325
|
+
isCadSearch
|
|
326
|
+
? '.stp,.step,.stl,.obj,.glb,.gltf,.heic,.heif,image/*'
|
|
327
|
+
: ''
|
|
328
|
+
}`}
|
|
327
329
|
id="icon-button-file"
|
|
328
330
|
type="file"
|
|
329
331
|
style={{ display: 'none' }}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
|
|
1
3
|
import { RectCoords } from '@nyris/nyris-api';
|
|
2
4
|
import { isEmpty } from 'lodash';
|
|
3
5
|
import { useCallback } from 'react';
|
|
@@ -61,15 +63,34 @@ export const useImageSearch = () => {
|
|
|
61
63
|
let res: any;
|
|
62
64
|
let compressedBase64;
|
|
63
65
|
|
|
66
|
+
let blob = image;
|
|
67
|
+
|
|
68
|
+
if (['.heic', '.heif'].some(ex => image?.name?.endsWith(ex))) {
|
|
69
|
+
const blobTemp = new Blob([image], { type: 'image/heif' });
|
|
70
|
+
const buffer = new Uint8Array(await blobTemp.arrayBuffer());
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
const convert = await import('heic-convert/browser');
|
|
74
|
+
|
|
75
|
+
let outputBuffer = await convert.default({
|
|
76
|
+
buffer: buffer, // the HEIC file buffer
|
|
77
|
+
format: 'JPEG', // output format
|
|
78
|
+
});
|
|
79
|
+
blob = new Blob([outputBuffer], { type: 'image/jpeg' });
|
|
80
|
+
} catch (error) {
|
|
81
|
+
console.log('HEIC conversion error:', error);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
64
85
|
if (compress) {
|
|
65
86
|
try {
|
|
66
|
-
compressedBase64 = await compressImage(
|
|
87
|
+
compressedBase64 = await compressImage(blob);
|
|
67
88
|
} catch (error) {}
|
|
68
89
|
}
|
|
69
90
|
|
|
70
|
-
let canvasImage = await createImage(compressedBase64 ||
|
|
91
|
+
let canvasImage = await createImage(compressedBase64 || blob);
|
|
71
92
|
|
|
72
|
-
let requestImage = await createImage(
|
|
93
|
+
let requestImage = await createImage(blob);
|
|
73
94
|
|
|
74
95
|
if (!imageRegion) {
|
|
75
96
|
dispatch(setRequestImage(canvasImage));
|
|
@@ -84,7 +105,9 @@ export const useImageSearch = () => {
|
|
|
84
105
|
region = res.selectedRegion;
|
|
85
106
|
dispatch(setSelectedRegion(region));
|
|
86
107
|
setImageRegions([region]);
|
|
87
|
-
} catch (error) {
|
|
108
|
+
} catch (error) {
|
|
109
|
+
console.log('Error finding regions', error);
|
|
110
|
+
}
|
|
88
111
|
}
|
|
89
112
|
|
|
90
113
|
const preFilterValues = [
|
package/src/translations.ts
CHANGED
|
@@ -14,7 +14,7 @@ export const translations = {
|
|
|
14
14
|
'Items per page': 'Items per page',
|
|
15
15
|
'Search with an image': 'Search with an image',
|
|
16
16
|
'Clear text search': 'Clear text search',
|
|
17
|
-
'View details': 'View details
|
|
17
|
+
'View details': 'View details',
|
|
18
18
|
'Clear image search': 'Clear image search ',
|
|
19
19
|
'Add or change pre-filter': 'Add or change pre-filter',
|
|
20
20
|
'Expand all': 'Expand all',
|
package/src/types.ts
CHANGED
|
@@ -65,6 +65,11 @@ interface Attributes {
|
|
|
65
65
|
attributeFourValue?: string;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
interface ProductDetailsAttribute {
|
|
69
|
+
propertyName: string;
|
|
70
|
+
value: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
68
73
|
export interface AppSettings extends NyrisAPISettings {
|
|
69
74
|
algolia: AlgoliaSettings;
|
|
70
75
|
alogoliaFilterField?: string;
|
|
@@ -75,6 +80,7 @@ export interface AppSettings extends NyrisAPISettings {
|
|
|
75
80
|
clarityId?: string;
|
|
76
81
|
mainTitle: string;
|
|
77
82
|
productDetails: string;
|
|
83
|
+
productDetailsAttribute?: ProductDetailsAttribute[];
|
|
78
84
|
secondaryTitle: string;
|
|
79
85
|
CTAButton?: CTAButtonSettings;
|
|
80
86
|
secondaryCTAButton?: SecondaryCTAButton;
|