@bytebrand/fe-ui-core 4.2.235 → 4.2.237

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bytebrand/fe-ui-core",
3
- "version": "4.2.235",
3
+ "version": "4.2.237",
4
4
  "description": "UI components for the auto.de project",
5
5
  "main": "index.ts",
6
6
  "module": "dist/common.js",
@@ -108,3 +108,40 @@
108
108
  display: block;
109
109
  border: none;
110
110
 
111
+ .noYoutubeWrapper
112
+ margin: 82px auto 0;
113
+ width: 487px;
114
+ display: flex;
115
+ flex-direction: column;
116
+ align-items: center;
117
+ +media-phone-only()
118
+ margin: 40px auto 0;
119
+ width: 297px;
120
+
121
+ svg
122
+ +media-phone-only()
123
+ width: 79px;
124
+ height: 56px;
125
+
126
+ .youtubeCookiesText
127
+ font-size: 28px;
128
+ font-weight: 400;
129
+ line-height: 36px;
130
+ margin:62px 0px 54px;
131
+ display: block;
132
+ text-align: center;
133
+ +media-phone-only()
134
+ margin: 36px auto 39px;
135
+ font-size:17px;
136
+ line-height: 21px
137
+
138
+ .btn
139
+ height: 38px!important
140
+ +media-phone-only()
141
+ height: 30px!important
142
+ font-size:13px;
143
+
144
+ .btn:first-child
145
+ margin-right:22px!important
146
+ +media-phone-only()
147
+ margin-right:5px!important
@@ -13,6 +13,10 @@ import withMagnifyGlassImage from '../_common/MagnifyGlass/MagnifyGlass';
13
13
  import { IImage, IPrice, SliderType } from '../../framework/types/types';
14
14
  import { PLACEHOLDER_IMAGE_SMALL_URL } from '../../framework/constants/common';
15
15
  import { VehicleDetailedSliderTranslate } from '../../locales/data';
16
+ import SvgYoutubeButton from '../_common/IconSVG/SVG/slider/YoutubeButton';
17
+ import Button from '../_common/Button/Button';
18
+ import { updateCookieList } from '../../framework/utils/CommonUtils';
19
+
16
20
 
17
21
 
18
22
  import styles from './VehicleDetailedSlider.styl';
@@ -20,26 +24,27 @@ import styles from './VehicleDetailedSlider.styl';
20
24
  interface IProps {
21
25
  t: (phrase: string, config?: any) => string;
22
26
  price: IPrice;
23
- photos: IImage [];
24
- exteriorPhotos: IImage [];
27
+ photos: IImage[];
28
+ exteriorPhotos: IImage[];
25
29
  interiorPhoto: IImage;
26
30
  mainImageUrl: string;
27
31
  mainImageBlur: boolean;
28
32
  statsData: any;
29
33
  isFavorite: boolean;
30
34
  showNewLabel: boolean;
31
- activeTab:number;
35
+ activeTab: number;
32
36
  make: string;
33
37
  model: string;
34
38
  subModel: string;
35
39
  powerKW: number;
36
40
  powerPS: number;
37
- financingConfig:any;
38
- youtubeId:string;
41
+ financingConfig: any;
42
+ youtubeId: string;
39
43
  showModal?: (id: string, props?: any) => void;
40
44
  hideModal: (id: string) => void;
41
45
  onCarFavorite: (event: MouseEvent<HTMLElement>) => void;
42
- showDownPayment:boolean;
46
+ showDownPayment: boolean;
47
+ handleSentryInit?: () => void;
43
48
  }
44
49
 
45
50
  interface IState {
@@ -48,7 +53,8 @@ interface IState {
48
53
  smallLoaded: boolean;
49
54
  largeLoaded1: boolean;
50
55
  largeLoaded01: boolean;
51
- videoSrc:string;
56
+ videoSrc: string;
57
+ showYoutube: boolean;
52
58
  }
53
59
 
54
60
  const MagnifyGlassImage = withMagnifyGlassImage(Image);
@@ -65,30 +71,33 @@ class VehicleDetailedSlider extends Component<IProps, IState> {
65
71
  };
66
72
 
67
73
  private slider: any;
68
-
74
+
69
75
  private imagesCache: string[] = [];
70
76
 
71
77
  constructor(props: IProps) {
72
-
73
78
  super(props);
79
+ const cookieConfig = JSON.parse(localStorage.getItem('cookieConfig')) || {};
80
+ const youtubeConfig = !cookieConfig?.marketing?.includes('youtube');
74
81
  this.state = {
75
82
  activeSlide: 0,
76
83
  largeLoaded: false,
77
84
  smallLoaded: false,
78
85
  largeLoaded1: false,
79
86
  largeLoaded01: false,
80
- videoSrc:''
81
-
87
+ videoSrc: '',
88
+ showYoutube: youtubeConfig
82
89
  };
83
90
  }
84
91
 
85
92
  handleSetFirstSlide = () => {
86
93
  this.slider.slickGoTo(0);
87
-
88
94
  };
89
95
 
90
96
 
91
- componentDidUpdate(prevProps: IProps) {
97
+ componentDidUpdate(prevProps: IProps, prevState: IState) {
98
+ const cookieConfig = JSON.parse(localStorage.getItem('cookieConfig')) || {};
99
+ const showYoutube = !cookieConfig?.marketing?.includes('youtube');
100
+ console.log('showYoutube', showYoutube);
92
101
  if (prevProps.photos.length !== this.props.photos.length && this.props.photos.length === 0) {
93
102
  this.setState(() => ({
94
103
  largeLoaded: false,
@@ -97,10 +106,15 @@ class VehicleDetailedSlider extends Component<IProps, IState> {
97
106
  largeLoaded01: false
98
107
  }));
99
108
  }
109
+ if (showYoutube !== prevState.showYoutube) {
110
+ this.setState(() => ({
111
+ showYoutube: showYoutube
112
+ }));
113
+ }
100
114
  }
101
115
 
102
116
  handleOpenSliderModal = (sliderType: SliderType) => {
103
- const { t = (phrase: string) => _get(VehicleDetailedSliderTranslate(statsData), phrase, phrase), photos, exteriorPhotos, interiorPhoto, showModal, hideModal, statsData } = this.props;
117
+ const { t = (phrase: string) => _get(VehicleDetailedSliderTranslate(statsData), phrase, phrase), photos, exteriorPhotos, interiorPhoto, showModal, hideModal, statsData, handleSentryInit } = this.props;
104
118
  const { activeSlide } = this.state;
105
119
 
106
120
  showModal('VEHICLE_DETAILED_SLIDER_MODAL', {
@@ -116,21 +130,22 @@ class VehicleDetailedSlider extends Component<IProps, IState> {
116
130
  onClose: (index: number) => {
117
131
  this.slider.slickGoTo(index, true);
118
132
  hideModal('VEHICLE_DETAILED_SLIDER_MODAL');
119
- }
133
+ },
134
+ handleSentryInit: handleSentryInit
120
135
  });
121
136
  };
122
137
 
123
138
  handleSlideChange = (_currentSlide: any, nextSlide: number) => {
124
139
  const { photos } = this.props;
125
140
  if (photos[nextSlide].videoUrl) {
126
- this.setState({ videoSrc: `https://www.youtube-nocookie.com/embed/${photos[nextSlide].videoUrl}` })
141
+ this.setState({ videoSrc: `https://www.youtube.com/embed/${photos[nextSlide].videoUrl}` })
127
142
  } else {
128
143
  this.setState({ videoSrc: null })
129
144
  }
130
145
  }
131
146
 
132
147
  getImages = () => {
133
- const { photos, mainImageUrl, mainImageBlur } = this.props;
148
+ const { photos, mainImageUrl, mainImageBlur, t, handleSentryInit } = this.props;
134
149
  const { activeSlide, largeLoaded, smallLoaded, largeLoaded1, largeLoaded01 } = this.state;
135
150
 
136
151
  const imageProps = {
@@ -164,13 +179,25 @@ class VehicleDetailedSlider extends Component<IProps, IState> {
164
179
  isMouseDown = false;
165
180
  isDragging = false;
166
181
  };
167
-
182
+
183
+ const updateCookies = () => {
184
+ const cookieConfig = localStorage.getItem('cookieConfig');
185
+ const conf = JSON.parse(cookieConfig);
186
+ const indexToRemove = conf.marketing.indexOf('youtube');
187
+ if (indexToRemove !== -1) {
188
+ conf.marketing.splice(indexToRemove, 1);
189
+ }
190
+ const showYoutube = !conf?.marketing?.includes('youtube');
191
+ this.setState({ showYoutube: showYoutube })
192
+ localStorage.setItem('cookieConfig', JSON.stringify(conf));
193
+ updateCookieList(handleSentryInit);
194
+ }
195
+
168
196
 
169
197
  const imagesCount = photos.length;
170
198
  const currentSlide = activeSlide;
171
199
  const prevSlide = (activeSlide - 1 % imagesCount + imagesCount) % imagesCount;
172
200
  const nextSlide = (activeSlide + 1 % imagesCount + imagesCount) % imagesCount;
173
-
174
201
  return photos.map((item: IImage, index: number) => {
175
202
  const showImage = index === currentSlide || index === prevSlide || index === nextSlide || this.imagesCache[index] !== undefined;
176
203
  const imageUrlSmall = _get(item, 'imageUrlSmall', null);
@@ -179,14 +206,13 @@ class VehicleDetailedSlider extends Component<IProps, IState> {
179
206
  this.imagesCache[currentSlide] = imageUrlLarge;
180
207
  this.imagesCache[prevSlide] = imageUrlLarge;
181
208
  this.imagesCache[nextSlide] = imageUrlLarge;
182
-
183
209
  return (
184
210
  <div
185
211
  className={styles.photo}
186
212
  key={imageUrlLarge}
187
213
  onMouseDown={handleMouseDown}
188
214
  onMouseMove={handleMouseMove}
189
- onMouseUp={handleMouseUp}
215
+ onMouseUp={this.state.showYoutube ? handleMouseUp : null}
190
216
  >
191
217
  {showImage && !item.videoUrl && (
192
218
  <MagnifyGlassImage
@@ -196,7 +222,7 @@ class VehicleDetailedSlider extends Component<IProps, IState> {
196
222
  {...imageProps}
197
223
  />
198
224
  )}
199
- {showImage && item.videoUrl && (
225
+ {showImage && item.videoUrl && this.state.showYoutube && (
200
226
  <iframe
201
227
  width='100%'
202
228
  height='441'
@@ -205,56 +231,68 @@ class VehicleDetailedSlider extends Component<IProps, IState> {
205
231
  className={styles.frame}
206
232
  ></iframe>
207
233
  )}
234
+ {showImage && item.videoUrl && !this.state.showYoutube && (
235
+ <div className={styles.noYoutubeWrapper}>
236
+ <SvgYoutubeButton></SvgYoutubeButton>
237
+ <span className={styles.youtubeCookiesText}>{t('youtube.acceptCookiesText')}</span>
238
+ <div>
239
+ <Button variant='text' className={styles.btn} onClick={() => window.open('https://www.youtube.com/howyoutubeworks/our-commitments/protecting-user-data/', '_blank')}>
240
+ {t('youtube.dataProtection')}
241
+ </Button>
242
+ <Button color='primary' className={styles.btn} onClick={updateCookies}>{t('youtube.allow')}</Button>
243
+ </div>
244
+ </div>
245
+ )}
208
246
  </div>
209
247
  );
210
248
  });
211
249
  }
212
250
  if (mainImageUrl) {
213
- const imagesCount = Array.isArray(photos) && photos.length > 0 ? photos.length : 0;
251
+ const imagesCount = Array.isArray(photos) && photos.length > 0 ? photos.length : 0;
214
252
  const prevSlide = (activeSlide - 1 % imagesCount + imagesCount) % imagesCount;
215
253
  const nextSlide = (activeSlide + 1 % imagesCount + imagesCount) % imagesCount;
216
254
  return (
217
- // preload cached photos from props
218
-
219
- <div className={classnames(styles.photo, { [styles.blurred]: (mainImageBlur && mainImageUrl !== PLACEHOLDER_IMAGE_SMALL_URL) })} key={mainImageUrl}>
220
- {(!largeLoaded || !smallLoaded || !largeLoaded1 || !largeLoaded01) && <Image src={mainImageUrl} {...imageProps} /> }
221
-
222
- { Array.isArray(photos) && photos.length > 0 && <Image
223
- style={ { display: 'none' } }
224
- src={ photos[activeSlide]?.imageUrlSmall }
225
- onLoad={ () => this.setState({ smallLoaded: true }) }
226
- {...imageProps}
227
- />
228
- }
229
- { Array.isArray(photos) && photos.length > 0 && <Image
230
- style={ { display: 'none' } }
231
- src={ photos[activeSlide]?.imageUrlLarge }
232
- onLoad={ () => this.setState({ largeLoaded: true }) }
233
- {...imageProps}
234
- />
235
- }
236
-
237
- { Array.isArray(photos) && photos.length > 0 && <Image
238
- style={ { display: 'none' } }
239
- src={ photos[nextSlide]?.imageUrlLarge }
240
- onLoad={ () => this.setState({ largeLoaded1: true }) }
241
- {...imageProps}
242
- />
243
- }
244
- { Array.isArray(photos) && photos.length > 0 && <Image
245
- style={ { display: 'none' } }
246
- src={ photos[prevSlide]?.imageUrlLarge }
247
- onLoad={ () => this.setState({ largeLoaded01: true }) }
248
- {...imageProps}
249
- />
250
- }
251
- </div>
255
+ // preload cached photos from props
256
+
257
+ <div className={classnames(styles.photo, { [styles.blurred]: (mainImageBlur && mainImageUrl !== PLACEHOLDER_IMAGE_SMALL_URL) })} key={mainImageUrl}>
258
+ {(!largeLoaded || !smallLoaded || !largeLoaded1 || !largeLoaded01) && <Image src={mainImageUrl} {...imageProps} />}
259
+
260
+ {Array.isArray(photos) && photos.length > 0 && <Image
261
+ style={{ display: 'none' }}
262
+ src={photos[activeSlide]?.imageUrlSmall}
263
+ onLoad={() => this.setState({ smallLoaded: true })}
264
+ {...imageProps}
265
+ />
266
+ }
267
+ {Array.isArray(photos) && photos.length > 0 && <Image
268
+ style={{ display: 'none' }}
269
+ src={photos[activeSlide]?.imageUrlLarge}
270
+ onLoad={() => this.setState({ largeLoaded: true })}
271
+ {...imageProps}
272
+ />
273
+ }
274
+
275
+ {Array.isArray(photos) && photos.length > 0 && <Image
276
+ style={{ display: 'none' }}
277
+ src={photos[nextSlide]?.imageUrlLarge}
278
+ onLoad={() => this.setState({ largeLoaded1: true })}
279
+ {...imageProps}
280
+ />
281
+ }
282
+ {Array.isArray(photos) && photos.length > 0 && <Image
283
+ style={{ display: 'none' }}
284
+ src={photos[prevSlide]?.imageUrlLarge}
285
+ onLoad={() => this.setState({ largeLoaded01: true })}
286
+ {...imageProps}
287
+ />
288
+ }
289
+ </div>
252
290
  );
253
291
 
254
292
  }
255
293
 
256
294
  return (
257
- <div className={styles.noPhoto}/>
295
+ <div className={styles.noPhoto} />
258
296
  );
259
297
  };
260
298
 
@@ -320,16 +358,16 @@ class VehicleDetailedSlider extends Component<IProps, IState> {
320
358
  return (
321
359
  <div className={styles.sliderWrap}>
322
360
  {isMobileOnly &&
323
- <Title {...{ t, make, model, subModel, powerKW, powerPS, onCarFavorite, isFavorite }}/>
361
+ <Title {...{ t, make, model, subModel, powerKW, powerPS, onCarFavorite, isFavorite }} />
324
362
  }
325
363
  <div className={styles.slider}>
326
- {!photos[activeSlide]?.videoUrl && <PriceData {...priceProps}/>}
364
+ {!photos[activeSlide]?.videoUrl && <PriceData {...priceProps} />}
327
365
  <Slider ref={slider => (this.slider = slider)} {...sliderProps}>
328
366
  {this.getImages()}
329
367
  </Slider>
330
368
  {!photos[activeSlide]?.videoUrl ? (
331
- isMobileOnly ? <MobileStats {...statsProps} /> : <Stats {...statsProps} />
332
- ) : null}
369
+ isMobileOnly ? <MobileStats {...statsProps} /> : <Stats {...statsProps} />
370
+ ) : null}
333
371
  </div>
334
372
  </div>
335
373
  );
@@ -236,6 +236,7 @@ import Easy from './SVG/slider/Easy';
236
236
  import Safe from './SVG/slider/Safe';
237
237
  import ZoomIn from './SVG/slider/ZoomIn';
238
238
  import ZoomOut from './SVG/slider/ZoomOut';
239
+ import YoutubeButton from './SVG/slider/YoutubeButton'
239
240
 
240
241
  // social
241
242
  import SharingInterface from './SVG/social/SharingInterface';
@@ -547,6 +548,7 @@ const components: IComponentsProp = {
547
548
  safe: Safe,
548
549
  zoomIn: ZoomIn,
549
550
  zoomOut: ZoomOut,
551
+ youtubeButton:YoutubeButton,
550
552
 
551
553
  // social
552
554
  sharingInterface: SharingInterface,
@@ -0,0 +1,26 @@
1
+ /* tslint:disable */
2
+ import * as React from 'react';
3
+
4
+ const SvgYoutubeButton = (props: any) => (
5
+ <svg
6
+ xmlns="http://www.w3.org/2000/svg"
7
+ width="146"
8
+ height="103"
9
+ viewBox="0 0 146 103"
10
+ fill="none"
11
+ {...props}
12
+ >
13
+ <g clipPath="url(#clip0_13856_24182)">
14
+ <path d="M142.741 16.6087C141.067 10.3215 137.398 4.99979 131.11 3.32604C119.716 0.278958 72.9583 0 72.9583 0C72.9583 0 26.2006 0.278958 14.8063 3.32604C8.51896 4.99979 4.87104 10.3215 3.17583 16.6087C0.12875 28.0031 0 51.5 0 51.5C0 51.5 0.12875 74.9969 3.17583 86.3912C4.84958 92.6785 8.51896 98.0002 14.8063 99.674C26.2006 102.721 72.9583 103 72.9583 103C72.9583 103 119.716 102.721 131.11 99.674C137.398 98.0002 141.067 92.6785 142.741 86.3912C145.788 74.9969 145.917 51.5 145.917 51.5C145.917 51.5 145.788 28.0031 142.741 16.6087Z" fill="#FF0000" />
15
+ <path d="M96.5625 51.5003L57.9375 30.042V72.9587" fill="white" />
16
+ </g>
17
+ <defs>
18
+ <clipPath id="clip0_13856_24182">
19
+ <rect width="145.917" height="103" fill="white" />
20
+ </clipPath>
21
+ </defs>
22
+ </svg>
23
+ );
24
+
25
+ export default SvgYoutubeButton;
26
+ /* tslint:enable */
@@ -20,7 +20,7 @@ const PreviewCookieModal = ({ toggleModal, setModal, handleSentryInit } : IPrevi
20
20
 
21
21
  const onDisableAll = () => {
22
22
  localStorage.setItem('cookieConfig', JSON.stringify({
23
- 'marketing':['cf','cip','cnac','car','test_cookie','IDE'],
23
+ 'marketing':['cf','cip','cnac','car','test_cookie','IDE', 'bid'],
24
24
  'analytics':['sentry','callback','locale','uid','PugT','demdex','cto_bundle','tuuid','tuuid_lu','c','CMID','CMPS','CMPRO','uuid2','um','umeh','KRTBCOOKIE_97','IDSYNC','dpm','_kuid_','visitor-id','data-c-ts','data-c','CMTS','mv_tokens','A3','mv_tokens_eu-v1','am_tokens','am_tokens_eu-v1','iteo','_fbp','_clck','_clsk','_uetsid','_uetvid','analytics_storage','ad_storage','functionality_storage','personalization_storage','security_storage','hotjar']
25
25
  }));
26
26
  updateCookieList(handleSentryInit);
@@ -30,7 +30,8 @@ export const COOKIE_SCHEMA_LINKS = {
30
30
  Microsoft: 'https://privacy.microsoft.com/de-de/privacystatement',
31
31
  Matomo: 'https://matomo.org/privacy-policy/',
32
32
  Trustpilot: 'https://de.legal.trustpilot.com/for-reviewers/end-user-privacy-terms',
33
- Awin: 'https://www.awin.com/de/datenschutzerklarung'
33
+ Awin: 'https://www.awin.com/de/datenschutzerklarung',
34
+ Youtube:'https://www.youtube.com/howyoutubeworks/our-commitments/protecting-user-data/'
34
35
  }
35
36
 
36
37
  export const COOKIE_SCHEMA = {
@@ -94,12 +95,15 @@ export const COOKIE_SCHEMA = {
94
95
  'cnac',
95
96
  'car'
96
97
  ],
98
+ Awin: [
99
+ 'bid'
100
+ ],
97
101
  Google: [
98
102
  'test_cookie',
99
103
  'IDE',
100
104
  ],
101
- Awin: [
102
- 'bid'
105
+ Youtube: [
106
+ 'youtube'
103
107
  ]
104
108
  }
105
109
  };
@@ -547,10 +547,11 @@ export function setUtmParameters() {
547
547
  const domain = parsedUrl.hostname.split('.').slice(-2).join('.');
548
548
 
549
549
  document.cookie = `marketing=${JSON.stringify(marketing)};expires=${expiresDate};domain=.${domain};path=/`;
550
+
550
551
  }
551
552
 
552
553
  export const updateCookieList = (handleSentryInit: () => void) => {
553
- const cookieConfig = JSON.parse(localStorage.getItem('cookieConfig')) || {};
554
+ const cookieConfig = JSON.parse(localStorage.getItem('marketing')) || {};
554
555
  let isSentryGranted = true; // Sentry
555
556
  let disabledCookies: any[] = [];
556
557
  const parsedUrl = new URL(window.location.href);