kitchen-simulator 5.0.0-test.25 → 5.0.0-test.27

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.
@@ -1,1526 +0,0 @@
1
- import Dialog from '@material-ui/core/Dialog';
2
- import axios from 'axios';
3
- import convert from 'convert-units';
4
- import { Plugins as PlannerPlugins } from './index';
5
- import PropTypes from 'prop-types';
6
- import React, { Component } from 'react';
7
- import ReactGA from 'react-ga4';
8
- import { hotjar } from 'react-hotjar';
9
- import { connect } from 'react-redux';
10
- import { bindActionCreators } from 'redux';
11
- import styled from 'styled-components';
12
- import SnackBar from './components/atoms/Snackbar';
13
- import AutosavePromptPopup from './components/toolbar/popup/autosaveprompt';
14
- import DownloadSummaryPopup from './components/toolbar/popup/downloadsummary';
15
- import NewProjectPopup from './components/toolbar/popup/newproject';
16
- import SaveDesignPopup from './components/toolbar/popup/savedesign';
17
- import SubmitForQuotePopup from './components/toolbar/popup/submitforquote';
18
- import * as constants from './constants';
19
- import {
20
- API_SERVER_URL,
21
- BG_COLOR_HOVER,
22
- CLIENTS_NAME,
23
- DEFAULT_FONT_FAMILY,
24
- LOCAL_STORAGE_CART_ACTION,
25
- LOCAL_STORAGE_ORIGINAL_TOKEN,
26
- LOCAL_STORAGE_TOKEN_NAME,
27
- LOCAL_STORAGE_TOKEN_VALUE,
28
- MODE,
29
- PRIMARY_GREEN_COLOR,
30
- SECONDARY_PURPLE_COLOR,
31
- TEXT_COLOR_NEUTRAL_1
32
- } from './constants';
33
- import _ from 'lodash';
34
- import { base64Decode, getPath } from './utils/helper';
35
- import { isEmpty } from './components/viewer2d/utils';
36
- import actions from './actions/export';
37
- import Catalog from './catalog/catalog';
38
- import { Project } from './class/export';
39
- import {
40
- Content,
41
- FooterBarComponents,
42
- HeaderComponents,
43
- MyProjectsComonents,
44
- SignComponents,
45
- ToolbarComponents,
46
- WizardStepComponents
47
- } from './components/export';
48
- import jwtService from './components/login/jwtService';
49
- import SubmitPromptPopup from './components/toolbar/popup/submitprompt/index';
50
- // import './styles/export';
51
- import Translator from './translator/translator';
52
- import { objectsMap } from './utils/objects-utils';
53
- import { VERSION } from './version';
54
- import ls from 'localstorage-slim';
55
-
56
- const AWS = require('aws-sdk');
57
-
58
- const StyledDialog = styled(Dialog)`
59
- .MuiDialog-paperWidthSm {
60
- border-radius: 10px;
61
- }
62
- `;
63
-
64
- export const StyledDialogContent = styled.span`
65
- font-family: ${DEFAULT_FONT_FAMILY};
66
- color: ${TEXT_COLOR_NEUTRAL_1};
67
- padding: 10px 30px;
68
- padding-top: 30px;
69
- `;
70
-
71
- export const StyledDialogAction = styled.div`
72
- display: flex;
73
- justify-content: flex-end;
74
- padding: 15px 30px 25px;
75
- `;
76
-
77
- export const StyledButton = styled.div`
78
- padding: 10px 20px;
79
- cursor: pointer;
80
- margin-right: 10px;
81
- color: ${SECONDARY_PURPLE_COLOR};
82
- font-weight: bold;
83
- font-family: ${DEFAULT_FONT_FAMILY};
84
- font-size: 16px;
85
- border-radius: 20px;
86
- :hover {
87
- background-color: ${BG_COLOR_HOVER};
88
- }
89
- `;
90
-
91
- const s3 = new AWS.S3({
92
- accessKeyId: process.env.REACT_APP_AWS_ID,
93
- secretAccessKey: process.env.REACT_APP_AWS_SECRET
94
- });
95
-
96
- const { Header } = HeaderComponents;
97
- const { Toolbar } = ToolbarComponents;
98
- const { FooterBar } = FooterBarComponents;
99
- const { WizardStep } = WizardStepComponents;
100
- const { Sign } = SignComponents;
101
- const { MyProjects } = MyProjectsComonents;
102
-
103
- const toolbarW = 0;
104
- const sidebarW = 250;
105
- const footerBarH = 20;
106
-
107
- const wrapperStyle = {
108
- display: 'flex',
109
- flexFlow: 'row nowrap'
110
- };
111
-
112
- const uploadFiles = (data, filePath) => {
113
- var p1 = new Promise((resolve, reject) => {
114
- const params = {
115
- Bucket: process.env.REACT_APP_AWS_BUCKET_NAME,
116
- Key: filePath,
117
- Body: data,
118
- ContentType: 'application/json',
119
- ACL: 'public-read'
120
- };
121
- s3.putObject(params, function (err, data) {
122
- if (err) {
123
- reject(err);
124
- return;
125
- }
126
- console.log('success');
127
- resolve([data.Location]);
128
- });
129
- });
130
- return p1;
131
- };
132
-
133
- let saveAlert = '';
134
- let saveInterval = '';
135
-
136
- class KitchenConfigurator extends Component {
137
- constructor(props) {
138
- super(props);
139
-
140
- // utm tracking
141
- const utmDetailParams = new URLSearchParams(
142
- this.props.location && this.props.location.search
143
- );
144
-
145
- const utmStrEncoded = utmDetailParams.get('details');
146
- let utmRequestData = null;
147
- if (utmStrEncoded) {
148
- try {
149
- utmRequestData = JSON.parse(base64Decode(utmStrEncoded));
150
- utmRequestData = JSON.parse(utmRequestData?.utm);
151
- } catch (e) {
152
- console.error('Cannot parse utm parameter: ', error);
153
- utmRequestData = null;
154
- }
155
- }
156
-
157
- this.state = {
158
- savePopupVisible: false,
159
- quotePopupVisible: false,
160
- assistPopupVisible: false,
161
- newProjectPopupVisible: false,
162
- isModalVisible: false,
163
- submitPromptVisible: false,
164
- stateSubmitType: constants.SUBMIT_REQUEST_ASSIST,
165
- savePromptVisible: false,
166
- isShowProperty: true,
167
- submitTosave: false,
168
- signOpen: false,
169
- myProjectsOpen: false,
170
- myProjectsToLogin: false,
171
- downloadPopupVisible: false,
172
-
173
- // For Toolbar Item
174
- toolbar: '',
175
- reviewQuotePopupOpened: false,
176
- floorOpened: false,
177
- cabinetOpened: false,
178
- applianceOpened: false,
179
- finishingOpened: false,
180
- doorStyleOpen: false,
181
- wizardStepOpend:
182
- this.props.match?.params?.pid === undefined ||
183
- this.props.match?.params?.pid === 'null'
184
- ? true
185
- : false,
186
- tutorialMouseEventsAdd: false,
187
- replaceCabinetFlag: false,
188
- isSnackBarOpen: false,
189
- isSnackBar1Open: false,
190
- redirectURL: '',
191
- snackBarMessage: '',
192
- isSaved: !!this.props.match?.params?.token,
193
- isLeaving: false
194
- };
195
-
196
- // For UTM tracking
197
- this.utm = {
198
- utm_source: utmRequestData?.source || 'source',
199
- utm_medium: utmRequestData?.medium || 'medium',
200
- utm_campaign: utmRequestData?.campaign || 'campaign',
201
- utm_term: utmRequestData?.term || 'term',
202
- utm_content: utmRequestData?.content || 'content',
203
- gclid: utmRequestData?.gclid || 'gclid',
204
- msclkid: utmRequestData?.msclkid || 'msclkid',
205
- fbclid: utmRequestData?.fbclid || 'fbclid',
206
- ttclid: utmRequestData?.ttclid || 'ttclid'
207
- };
208
-
209
- this.jwtCheck();
210
-
211
- this.openFloor = this.openFloor.bind(this);
212
- this.openCabinet = this.openCabinet.bind(this);
213
- this.openFinishing = this.openFinishing.bind(this);
214
- this.openAppliance = this.openAppliance.bind(this);
215
- this.toggleDoorStyle = this.toggleDoorStyle.bind(this);
216
- this.onReviewQuoteClicked = this.onReviewQuoteClicked.bind(this);
217
- this.closeFloorTB = this.closeFloorTB.bind(this);
218
- this.closeCabinetTB = this.closeCabinetTB.bind(this);
219
- this.closeFinishingTB = this.closeFinishingTB.bind(this);
220
- this.closeApplianceTB = this.closeApplianceTB.bind(this);
221
- this.setToolbar = this.setToolbar.bind(this);
222
- this.replaceCabinet = this.replaceCabinet.bind(this);
223
- this.setSubmitToSave = this.setSubmitToSave.bind(this);
224
- this.setSignOpen = this.setSignOpen.bind(this);
225
- this.setMyProjectsOpen = this.setMyProjectsOpen.bind(this);
226
- this.setMyProjectsToLogin = this.setMyProjectsToLogin.bind(this);
227
- this.setDownloadPopupVisible = this.setDownloadPopupVisible.bind(this);
228
- this.neverShowInput = React.createRef(null);
229
- this.setShowProperty = this.setShowProperty.bind(this);
230
- }
231
-
232
- // Toolbar control functions
233
-
234
- setToolbar(toolBarKey) {
235
- this.setState({ toolbar: toolBarKey });
236
- }
237
-
238
- setShowProperty(value) {
239
- this.setState({ isShowProperty: value });
240
- }
241
-
242
- setMyProjectsOpen(value) {
243
- this.setState({ myProjectsOpen: value });
244
- this.setState({ signOpen: false });
245
- this.setState({ wizardStepOpend: false });
246
- }
247
-
248
- setMyProjectsToLogin(value) {
249
- this.setState({ myProjectsToLogin: value });
250
- }
251
-
252
- setDownloadPopupVisible(value) {
253
- this.setState({ reviewQuotePopupOpened: false });
254
- this.setState({ savePopupVisible: false });
255
- this.setState({ quotePopupVisible: false });
256
- this.setState({ submitTosave: false });
257
- this.setState({ assistPopupVisible: false });
258
- this.setState({ newProjectPopupVisible: false });
259
- this.setState({ downloadPopupVisible: value });
260
- }
261
-
262
- setSubmitToSave(value) {
263
- this.setState({ submitTosave: value });
264
- }
265
-
266
- setSignOpen(value) {
267
- this.setState({ wizardStepOpend: false });
268
- this.setState({ myProjectsOpen: false });
269
- this.setState({ signOpen: value });
270
- }
271
-
272
- openFloor() {
273
- this.setState({ floorOpened: true });
274
- document.getElementById(
275
- 'make_floorplan_inactive'
276
- ).parentElement.parentElement.style.zIndex = 999;
277
- }
278
-
279
- openCabinet() {
280
- this.setState({ cabinetOpened: true });
281
- document.getElementById(
282
- 'add_cabinets_inactive'
283
- ).parentElement.parentElement.style.zIndex = 999;
284
- }
285
-
286
- toggleDoorStyle(visible) {
287
- this.setState({ doorStyleOpen: visible });
288
- document.getElementById(
289
- 'select_doorstyle_inactive'
290
- ).parentElement.parentElement.style.zIndex = visible ? 999 : 6;
291
- }
292
-
293
- replaceCabinet(value) {
294
- this.setState({ replaceCabinetFlag: value });
295
- }
296
-
297
- openAppliance() {
298
- this.setState({ applianceOpened: true });
299
- document.getElementById(
300
- 'add_appliances_inactive'
301
- ).parentElement.parentElement.style.zIndex = 999;
302
- }
303
-
304
- openFinishing() {
305
- this.setState({ finishingOpened: true });
306
- document.getElementById(
307
- 'finishing_touches_inactive'
308
- ).parentElement.parentElement.style.zIndex = 999;
309
- }
310
-
311
- onReviewQuoteClicked(visible) {
312
- this.setState({ reviewQuotePopupOpened: visible });
313
- document.getElementById(
314
- 'review_quote_inactive'
315
- ).parentElement.parentElement.style.zIndex = visible ? 999 : 6;
316
- }
317
-
318
- closeFloorTB() {
319
- this.setState({ floorOpened: false });
320
- document.getElementById('make_floorplan_inactive') &&
321
- (document.getElementById(
322
- 'make_floorplan_inactive'
323
- ).parentElement.parentElement.style.zIndex = 6);
324
- }
325
-
326
- closeCabinetTB() {
327
- this.setState({ cabinetOpened: false });
328
- document.getElementById(
329
- 'add_cabinets_inactive'
330
- ).parentElement.parentElement.style.zIndex = 6;
331
- }
332
-
333
- closeFinishingTB() {
334
- this.setState({ finishingOpened: false });
335
- document.getElementById(
336
- 'finishing_touches_inactive'
337
- ).parentElement.parentElement.style.zIndex = 6;
338
- }
339
-
340
- closeApplianceTB() {
341
- this.setState({ applianceOpened: false });
342
- document.getElementById(
343
- 'add_appliances_inactive'
344
- ).parentElement.parentElement.style.zIndex = 6;
345
- }
346
-
347
- closeDoorstyle() {
348
- this.setState({});
349
- document.getElementById(
350
- 'select_doorstyle_inactive'
351
- ).parentElement.parentElement.style.zIndex = 6;
352
- }
353
- closeReviewQuote() {
354
- this.setState({});
355
- document.getElementById(
356
- 'review_quote_inactive'
357
- ).parentElement.parentElement.style.zIndex = 6;
358
- }
359
-
360
- jwtCheck() {
361
- jwtService.on('onAutoLogin', () => {
362
- // this.props.showMessage({message: 'Logging in with JWT'});
363
-
364
- /**
365
- * Sign in and retrieve user data from Api
366
- */
367
- jwtService
368
- .signInWithToken()
369
- .then(user => {
370
- //this.props.userActions.setUserData(user);
371
- this.props.userActions.login(
372
- user.id,
373
- user.role,
374
- jwtService.getAccessToken(),
375
- this.utm
376
- );
377
- //this.props.showMessage(option)
378
- //this.props.showMessage({message: 'Logged in with token data', variant: 'success'});
379
- //alert('Logged in with token data');
380
- })
381
- .catch(error => {
382
- //this.props.showMessage({message: error});
383
- this.setState({
384
- isSnackBarOpen: true,
385
- snackBarMessage: error
386
- });
387
- });
388
- });
389
-
390
- jwtService.on('onAutoLogout', message => {
391
- if (message) {
392
- //this.props.showMessage({message, variant: 'error'});
393
- }
394
- this.props.userActions.logout();
395
- });
396
-
397
- jwtService.init();
398
- }
399
-
400
- getChildContext() {
401
- return {
402
- ...objectsMap(actions, actionNamespace => this.props[actionNamespace]),
403
- translator: this.props.translator,
404
- catalog: this.props.catalog
405
- };
406
- }
407
-
408
- saveProjectToStorage() {
409
- let { state, stateExtractor } = this.props;
410
- const extractedState = stateExtractor(state);
411
- const projectData = JSON.stringify(extractedState.get('scene').toJS());
412
- sessionStorage.setItem(window.location.href, projectData);
413
- }
414
-
415
- debouncedSetIsSaved = _.debounce(
416
- () => this.setState({ isSaved: false }),
417
- 200
418
- );
419
-
420
- componentDidUpdate(prevProps) {
421
- // Only strip properties if the object is not null/undefined
422
- function stripProperty(obj, properties) {
423
- if (!obj) return obj;
424
- let changed = false;
425
- const newObj = { ...obj };
426
- for (const prop of properties) {
427
- if (prop in newObj) {
428
- delete newObj[prop];
429
- changed = true;
430
- }
431
- }
432
- return changed ? newObj : obj;
433
- }
434
-
435
- const prevState = this.props.stateExtractor(prevProps.state);
436
- const currState = this.props.stateExtractor(this.props.state);
437
-
438
- // Only convert to JS once per items/areas/lines
439
- const prevLayer = prevState.scene.selectedLayer;
440
- const currLayer = currState.scene.selectedLayer;
441
-
442
- const prevItems = prevState
443
- .getIn(['scene', 'layers', prevLayer, 'items'])
444
- .toJS();
445
- const currItems = currState
446
- .getIn(['scene', 'layers', currLayer, 'items'])
447
- .toJS();
448
-
449
- const prevItemsProps = Object.values(prevItems).map(
450
- ({ x, y, rotation }) => ({ x, y, rotation })
451
- );
452
- const currItemsProps = Object.values(currItems).map(
453
- ({ x, y, rotation }) => ({ x, y, rotation })
454
- );
455
-
456
- const prevDoorStyleRaw = prevState.getIn([
457
- 'scene',
458
- 'layers',
459
- prevLayer,
460
- 'doorStyle'
461
- ]);
462
- const currDoorStyleRaw = currState.getIn([
463
- 'scene',
464
- 'layers',
465
- currLayer,
466
- 'doorStyle'
467
- ]);
468
- const prevDoorStyle = stripProperty(prevDoorStyleRaw, ['doorStyles']);
469
- const currDoorStyle = stripProperty(currDoorStyleRaw, ['doorStyles']);
470
-
471
- const prevAreasRaw = prevState
472
- .getIn(['scene', 'layers', prevLayer, 'areas'])
473
- .toJS();
474
- const currAreasRaw = currState
475
- .getIn(['scene', 'layers', currLayer, 'areas'])
476
- .toJS();
477
- const prevAreas = stripProperty(Object.values(prevAreasRaw)[0], [
478
- 'selected'
479
- ]);
480
- const currAreas = stripProperty(Object.values(currAreasRaw)[0], [
481
- 'selected'
482
- ]);
483
-
484
- const prevLinesRaw = prevState
485
- .getIn(['scene', 'layers', prevLayer, 'lines'])
486
- .toJS();
487
- const currLinesRaw = currState
488
- .getIn(['scene', 'layers', currLayer, 'lines'])
489
- .toJS();
490
- const prevLines = stripProperty(Object.values(prevLinesRaw)[0], [
491
- 'selected'
492
- ]);
493
- const currLines = stripProperty(Object.values(currLinesRaw)[0], [
494
- 'selected'
495
- ]);
496
-
497
- const prevCeilingHeight = prevState.getIn([
498
- 'scene',
499
- 'layers',
500
- prevLayer,
501
- 'ceilHeight'
502
- ]);
503
- const currCeilingHeight = currState.getIn([
504
- 'scene',
505
- 'layers',
506
- currLayer,
507
- 'ceilHeight'
508
- ]);
509
-
510
- let changed =
511
- !_.isEqual(prevItemsProps, currItemsProps) ||
512
- !_.isEqual(prevDoorStyle, currDoorStyle) ||
513
- !_.isEqual(prevAreas, currAreas) ||
514
- !_.isEqual(prevLines, currLines) ||
515
- prevCeilingHeight !== currCeilingHeight;
516
-
517
- if (changed) {
518
- this.debouncedSetIsSaved();
519
-
520
- const currentItemsLength = Object.keys(currItems).length;
521
- const prevItemsLength = Object.keys(prevItems).length;
522
- // make sure prompt appears only when adding cabinets
523
- const allowedItemLengths = [5, 10, 15];
524
-
525
- if (
526
- allowedItemLengths.includes(currentItemsLength) &&
527
- prevItemsLength === currentItemsLength - 1 &&
528
- !this.props.match.params.token
529
- ) {
530
- this.setState({ savePromptVisible: true });
531
- }
532
- }
533
- }
534
-
535
- handleBeforeUnload = e => {
536
- const areas = this.props
537
- .stateExtractor(this.props.state)
538
- .getIn([
539
- 'scene',
540
- 'layers',
541
- this.props.stateExtractor(this.props.state).scene.selectedLayer,
542
- 'areas'
543
- ]);
544
-
545
- if (!this.state.isSaved && areas.size > 0) {
546
- setTimeout(() => {
547
- this.setState({ savePromptVisible: true, isLeaving: true });
548
- }, 500);
549
-
550
- this.saveProjectToStorage();
551
-
552
- // This line is required to trigger the browser confirmation dialog
553
- e.preventDefault();
554
- e.returnValue = '';
555
- return '';
556
- }
557
- };
558
-
559
- componentDidMount() {
560
- ReactGA.send({ hitType: 'pageview', page: getPath() });
561
- hotjar.event && hotjar.event(`pageview:${getPath()}`);
562
-
563
- window.addEventListener('beforeunload', this.handleBeforeUnload);
564
-
565
- window.forRedo = [];
566
- let { store } = this.context;
567
- let { projectActions, catalog, stateExtractor, state, plugins } =
568
- this.props;
569
-
570
- projectActions.initCatalog(catalog);
571
-
572
- let { match } = this.props;
573
-
574
- if (sessionStorage.getItem(window.location.href)) {
575
- const jsonData = sessionStorage.getItem(window.location.href);
576
- projectActions.loadProject(JSON.parse(jsonData), this.props.categoryData);
577
- sessionStorage.removeItem(window.location.href);
578
- return;
579
- }
580
-
581
- if (match && match.params.pid === undefined) {
582
- let newplugins = [
583
- ...plugins,
584
- PlannerPlugins.Autosave('KitchenConfigurator_v0', false)
585
- ];
586
- newplugins.forEach(newplugin => newplugin(store, stateExtractor));
587
- projectActions.newProject();
588
- sessionStorage.setItem('projectTitle', 'Untitled');
589
- projectActions.rename('Untitled');
590
- sessionStorage.removeItem('projectId');
591
- sessionStorage.removeItem('email');
592
- sessionStorage.removeItem('firstName');
593
- sessionStorage.removeItem('lastName');
594
- sessionStorage.removeItem('usedObjects');
595
- return;
596
- }
597
-
598
- if (match && match.params.pid !== undefined) {
599
- if (match.params.pid === 'new') {
600
- projectActions.newProject();
601
- sessionStorage.setItem('projectTitle', 'Untitled');
602
- projectActions.rename('Untitled');
603
- sessionStorage.removeItem('projectId');
604
- sessionStorage.removeItem('email');
605
- sessionStorage.removeItem('firstName');
606
- sessionStorage.removeItem('lastName');
607
- sessionStorage.removeItem('usedObjects');
608
- } else {
609
- axios
610
- .post(`${constants.API_SERVER_URL}/api/project/loadPidProject`, {
611
- pid: match.params.pid,
612
- visualizerName: sessionStorage.getItem('visualizerName')
613
- })
614
- .then(async response => {
615
- const { projectElement } = response.data;
616
- if (projectElement.length === 0) return;
617
- sessionStorage.setItem('projectTitle', projectElement[0].title);
618
- projectActions.rename(projectElement[0].title);
619
- sessionStorage.setItem('projectId', projectElement[0].id);
620
- sessionStorage.setItem('email', projectElement[0].email);
621
- sessionStorage.setItem('firstName', projectElement[0].firstName);
622
- sessionStorage.setItem('lastName', projectElement[0].lastName);
623
- sessionStorage.setItem('phone', projectElement[0].phone);
624
- let jsonData;
625
- if (projectElement[0].project_data) {
626
- jsonData = JSON.parse(projectElement[0].project_data);
627
- } else {
628
- try {
629
- jsonData = await axios.post(
630
- `${constants.API_SERVER_URL}/api/project/loadPidData`,
631
- { pid: match.params.pid }
632
- ).data.data;
633
- } catch (err) {
634
- this.setState({
635
- isSnackBarOpen: true,
636
- snackBarMessage: err
637
- });
638
- }
639
- }
640
- jsonData.isLoadingCabinet = false;
641
- projectActions.loadProject(jsonData, this.props.categoryData);
642
- });
643
- }
644
-
645
- sessionStorage.removeItem('user_type');
646
- sessionStorage.removeItem('project_type');
647
- sessionStorage.removeItem('project_timeline');
648
- }
649
- }
650
-
651
- componentWillUnmount() {
652
- window.addEventListener('beforeunload', this.handleBeforeUnload);
653
- window.onbeforeunload = null;
654
- }
655
-
656
- componentWillMount() {}
657
-
658
- componentWillReceiveProps(nextProps) {
659
- let { stateExtractor, state, projectActions, catalog } = nextProps;
660
- let plannerState = stateExtractor(state);
661
- let catalogReady = plannerState.getIn(['catalog', 'ready']);
662
- if (!catalogReady) {
663
- projectActions.initCatalog(catalog);
664
- }
665
- }
666
-
667
- isProjectEmpty(scene) {
668
- let { layers, selectedLayer } = scene;
669
- let layer = layers.get(selectedLayer);
670
- return (
671
- layer.areas.size +
672
- layer.lines.size +
673
- layer.holes.size +
674
- layer.items.size ===
675
- 0
676
- );
677
- }
678
-
679
- handleSaveDesign(value) {
680
- let { stateExtractor, state } = this.props;
681
- let plannerState = stateExtractor(state);
682
- let items = plannerState.getIn(['scene', 'layers', 'layer-1', 'items']);
683
- let areas = plannerState.getIn(['scene', 'layers', 'layer-1', 'areas']);
684
- if (areas.size === 0) {
685
- this.setState({
686
- isSnackBarOpen: true,
687
- snackBarMessage: 'Your project is empty.'
688
- });
689
- return;
690
- }
691
- // if (items.size === 0) {
692
- // saveAlert = <StyledAlert text={<span style={{fontSize: 16, fontFamily: DEFAULT_FONT_FAMILY}}>Add at least one item</span>} onClose={() => saveAlert = ""} />
693
- // return;
694
- // } else saveAlert = '';
695
- this.setState({ reviewQuotePopupOpened: false });
696
- this.setState({ savePopupVisible: value });
697
- this.setState({ assistPopupVisible: false });
698
- this.setState({ newProjectPopupVisible: false });
699
- this.setState({ savePromptVisible: false });
700
- this.setState({ submitPromptVisible: false });
701
- }
702
-
703
- handleNewProject(value) {
704
- this.setState({ reviewQuotePopupOpened: false });
705
- this.setState({ savePopupVisible: false });
706
- this.setState({ quotePopupVisible: false });
707
- this.setState({ assistPopupVisible: false });
708
- this.setState({ newProjectPopupVisible: value });
709
- }
710
-
711
- handleSubmitForQuote(
712
- isVisible,
713
- submitType = constants.SUBMIT_REQUEST_ASSIST
714
- ) {
715
- const items = this.props
716
- .stateExtractor(this.props.state)
717
- .getIn([
718
- 'scene',
719
- 'layers',
720
- this.props.stateExtractor(this.props.state).scene.selectedLayer,
721
- 'items'
722
- ]);
723
-
724
- if (submitType === constants.SUBMIT_ADD_CART) {
725
- this.setToolbar('reviewforquote');
726
- }
727
-
728
- if (submitType === constants.SUBMIT_ADD_CART && !items.size) {
729
- this.setState({
730
- isSnackBarOpen: true,
731
- snackBarMessage: 'Your project is empty. Please add at least one item.'
732
- });
733
- } else {
734
- this.setState({ reviewQuotePopupOpened: false });
735
- this.setState({ savePopupVisible: false });
736
- this.setState({ quotePopupVisible: isVisible });
737
- this.setState({ submitTosave: false });
738
- this.setState({ assistPopupVisible: false });
739
- this.setState({ newProjectPopupVisible: false });
740
- this.setState({ stateSubmitType: submitType });
741
- }
742
- }
743
-
744
- saveScreenshotToFile = event => {
745
- event.preventDefault();
746
- let canvas = document.getElementsByID('viewer3D')[1];
747
- let canvas_crop_image = document.getElementById('canvas_crop_image');
748
- let ctx = canvas_crop_image.getContext('2d');
749
-
750
- // Set width and height for the new canvas
751
- let heightAtt = document.createAttribute('height');
752
- heightAtt.value = canvas.height;
753
- canvas_crop_image.setAttributeNode(heightAtt);
754
-
755
- let widthAtt = document.createAttribute('width');
756
- widthAtt.value = canvas.width;
757
- canvas_crop_image.setAttributeNode(widthAtt);
758
-
759
- ctx.fillStyle = 'white';
760
- ctx.fillRect(0, 0, canvas_crop_image.width, canvas_crop_image.height);
761
-
762
- let img = new Image();
763
- img.crossOrigin = 'anonymous';
764
- img.src = canvas.toDataURL();
765
-
766
- img.onload = () => {
767
- ctx.globalAlpha = 0.3;
768
- ctx.drawImage(
769
- img,
770
- 0,
771
- 0,
772
- canvas_crop_image.width,
773
- canvas_crop_image.height
774
- );
775
- this.setState({
776
- isModalVisible: true,
777
- imageUri: canvas.toDataURL(),
778
- image: img
779
- });
780
- canvas_crop_image.style.zIndex = 11;
781
- document.addEventListener('keydown', this.onKeyDown, false);
782
- document.addEventListener(
783
- 'mouseup',
784
- this.onMouseUp_On_New_Save_SQ_DA,
785
- false
786
- );
787
- canvas_crop_image.style.display = 'block';
788
- };
789
- };
790
-
791
- findDelkeys(obj, deleteKeys, path) {
792
- if (typeof obj === 'object') {
793
- let allkeys = Object.keys(obj);
794
- for (let i = 0; i < allkeys.length; i++) {
795
- const value = obj[allkeys[i]];
796
- if (isEmpty(value)) {
797
- deleteKeys.push({
798
- path: path,
799
- key: allkeys[i]
800
- });
801
- } else if (typeof value === 'object') {
802
- let newPath = path + allkeys[i] + ',';
803
- this.findDelkeys(value, deleteKeys, newPath);
804
- }
805
- }
806
- } else if (isEmpty(obj)) {
807
- let tmpkey = path.split(',');
808
- deleteKeys.push({
809
- path: path,
810
- key: tmpkey[tmpkey.length - 1]
811
- });
812
- }
813
- }
814
-
815
- render() {
816
- let { width, height, state, stateExtractor, ...props } = this.props;
817
- let {
818
- savePopupVisible,
819
- quotePopupVisible,
820
- assistPopupVisible,
821
- newProjectPopupVisible,
822
- savePromptVisible,
823
- isLeaving,
824
- submitPromptVisible,
825
- stateSubmitType,
826
- submitTosave,
827
- signOpen,
828
- myProjectsOpen,
829
- myProjectsToLogin,
830
- downloadPopupVisible
831
- } = this.state;
832
- let contentW = width - toolbarW;
833
- let categoryData = this.props.categoryData;
834
- // console.log(categoryData);
835
- // let contentW = width - toolbarW - sidebarW;
836
- // let toolbarH = height - footerBarH;
837
- // let contentH = height - footerBarH;
838
- // let sidebarH = height - footerBarH;
839
- let toolbarH = height;
840
- let contentH = height;
841
- let sidebarH = height;
842
- let headerW = width;
843
- let headerH = 60;
844
-
845
- const userInfo = this.props.match ? this.props.match.params : [];
846
-
847
- let extractedState = stateExtractor(state);
848
- //console.log('KC state - mode: ', extractedState.mode);
849
- let doorStyle = extractedState.get('doorStyle');
850
- if (
851
- extractedState.getIn([
852
- 'scene',
853
- 'layers',
854
- extractedState.scene.selectedLayer,
855
- 'doorStyle'
856
- ]) !== undefined &&
857
- extractedState.getIn([
858
- 'scene',
859
- 'layers',
860
- extractedState.scene.selectedLayer,
861
- 'doorStyle'
862
- ]) !== null
863
- ) {
864
- const extractedStateData = extractedState.getIn([
865
- 'scene',
866
- 'layers',
867
- extractedState.scene.selectedLayer,
868
- 'doorStyle'
869
- ]);
870
- let doorIdAvailable = false;
871
- if (
872
- this.props.categoryData.doorStyles &&
873
- this.props.categoryData.doorStyles.items
874
- ) {
875
- this.props.categoryData.doorStyles.items.find(category => {
876
- doorIdAvailable = category.items.find(style => {
877
- let item = style.items.find(it => it.id === extractedStateData.id);
878
- if (item) {
879
- colorItem = item;
880
- return true;
881
- } else {
882
- return false;
883
- }
884
- });
885
- });
886
- }
887
-
888
- if (doorIdAvailable) doorStyle = extractedStateData;
889
- }
890
-
891
- let firstVisit =
892
- this.state.wizardStepOpend && this.isProjectEmpty(extractedState.scene);
893
- let allVisible = firstVisit || signOpen || myProjectsOpen;
894
-
895
- let _scene = extractedState.getIn(['scene']);
896
- let len = convert(_scene.width).from(_scene.unit).to('cm');
897
- let _viewer2D = extractedState.getIn(['viewer2D']);
898
- if (_viewer2D.size > 0) {
899
- let scaleX = (width / len) * 3;
900
- let scaleY = (height / len) * 3;
901
- let scale = scaleX > scaleY ? scaleY : scaleX;
902
- let _e = width - len * scale,
903
- _f = height - len * scale;
904
- let viewer = _viewer2D.toJS();
905
- if (viewer.e === 0 && viewer.f === 0) {
906
- _viewer2D = _viewer2D.merge({
907
- e: viewer.viewerWidth / 2 - viewer.SVGWidth / 2,
908
- f: viewer.viewerHeight / 2 - viewer.SVGHeight / 2,
909
- a: 0.99,
910
- d: 0.99
911
- });
912
- }
913
- }
914
- extractedState = extractedState.merge({
915
- viewer2D: _viewer2D
916
- });
917
-
918
- var history = this.props.history;
919
-
920
- let handleContinueQuote = () => {
921
- this.setToolbar('reviewforquote');
922
- this.setState({ savePopupVisible: false, quotePopupVisible: true });
923
- };
924
-
925
- let newProject = () => {
926
- this.props.projectActions.newProject();
927
- sessionStorage.setItem('projectTitle', 'Untitled');
928
- this.props.projectActions.rename('Untitled');
929
- sessionStorage.removeItem('projectId');
930
- sessionStorage.removeItem('usedObjects');
931
- const visualizerName = sessionStorage.getItem('visualizerName');
932
- const originalAccessToken = ls.get(LOCAL_STORAGE_ORIGINAL_TOKEN);
933
- const tokenName = ls.get(LOCAL_STORAGE_TOKEN_NAME);
934
-
935
- let pathname = `/${visualizerName}`;
936
- if (tokenName && originalAccessToken) {
937
- pathname += `?${tokenName}${originalAccessToken}`;
938
- }
939
-
940
- history.push({ pathname });
941
- this.setState({ wizardStepOpend: false });
942
- };
943
-
944
- /**
945
- * @description Save Projects
946
- * @param {{email,firstName,lastName,notes,projectName}} param Project information to save
947
- */
948
- let saveProject = async param => {
949
- let rlt = { success: false };
950
-
951
- // Get storage info
952
- let title = sessionStorage.getItem('projectTitle');
953
- let projectId = sessionStorage.getItem('projectId');
954
-
955
- let projectTitle =
956
- (param && param.projectName) ||
957
- title ||
958
- `Project-${new Date().toLocaleString()}`;
959
- let utm = this.utm;
960
-
961
- // State
962
- let state = Project.unselectAll(extractedState).updatedState;
963
- let { scene } = state;
964
- state = state.merge({ scene: scene.merge({ title: projectTitle }) });
965
-
966
- // Set storage info
967
- sessionStorage.setItem('projectTitle', projectTitle);
968
- props.projectActions.rename(projectTitle);
969
-
970
- // Filter cds
971
- const itemData = state
972
- .getIn([
973
- 'scene',
974
- 'layers',
975
- state.get('scene').toJS().selectedLayer,
976
- 'items'
977
- ])
978
- .toArray();
979
-
980
- itemData.forEach(it => {
981
- const item = it.toJS();
982
- const doorStyles = item?.doorStyle?.doorStyles;
983
-
984
- // Skip if no doorStyles data at all
985
- if (!doorStyles) return;
986
-
987
- const newCDSdata = Array.isArray(doorStyles.cds)
988
- ? doorStyles.cds.filter(
989
- it1 =>
990
- it1.cabinet_door_style_id === doorStyles.cabinet_door_style_id
991
- )
992
- : [];
993
-
994
- const layerId = state.get('scene').toJS().selectedLayer;
995
- const basePath = [
996
- 'scene',
997
- 'layers',
998
- layerId,
999
- 'items',
1000
- it.id,
1001
- 'doorStyle',
1002
- 'doorStyles'
1003
- ];
1004
-
1005
- if (state.hasIn(basePath)) {
1006
- state = state.setIn([...basePath, 'cds'], newCDSdata);
1007
- }
1008
- });
1009
-
1010
- // Delete null values
1011
-
1012
- let newScene = state.getIn(['scene']);
1013
- let deleteKeys = [];
1014
- this.findDelkeys(newScene.toJS(), deleteKeys, '');
1015
- for (let i = 0; i < deleteKeys.length; i++) {
1016
- let tmp = newScene.toJS();
1017
- let deletePath = deleteKeys[i].path.split(',');
1018
- for (let j = 0; j < deletePath.length; j++) {
1019
- if (!isEmpty(deletePath[j])) {
1020
- tmp = tmp[deletePath[j]];
1021
- }
1022
- }
1023
- if (deletePath.length >= 2) {
1024
- delete tmp[deleteKeys[i].key];
1025
- deletePath.pop();
1026
- if (!isEmpty(newScene.getIn(deletePath)))
1027
- newScene = newScene.setIn(deletePath, tmp);
1028
- } else {
1029
- newScene = newScene.delete(deleteKeys[i].key);
1030
- }
1031
- }
1032
-
1033
- state = state.setIn(['scene'], newScene);
1034
-
1035
- // Data to save
1036
- const projectData = JSON.stringify(state.get('scene').toJS());
1037
-
1038
- const object_count = Object.keys(
1039
- state?.scene?.layers?.get(state?.scene?.selectedLayer)?.items || {}
1040
- ).length;
1041
-
1042
- try {
1043
- const originalAccessToken = ls.get(LOCAL_STORAGE_ORIGINAL_TOKEN);
1044
- const tokenName = ls.get(LOCAL_STORAGE_TOKEN_NAME);
1045
-
1046
- const response = await axios.post('/api/project/saveProject', {
1047
- pid: projectId,
1048
- title: projectTitle,
1049
- mode: MODE,
1050
- access_token: userInfo.token ? userInfo.token : null,
1051
- userrole: userInfo.role ? userInfo.role : null,
1052
- saveData: { ...param, ...utm, projectData, object_count },
1053
- url: window.location.hostname,
1054
- visualizerName: sessionStorage.getItem('visualizerName'),
1055
- ...(originalAccessToken
1056
- ? { original_token: originalAccessToken }
1057
- : undefined),
1058
- ...(tokenName ? { query_params_token_prefix: tokenName } : undefined)
1059
- });
1060
-
1061
- const { success, message, userData, access_token } = response.data;
1062
- if (success === true) {
1063
- rlt.success = true;
1064
-
1065
- const { insertId } = response.data.execResult;
1066
- const currentProjectID =
1067
- insertId !== 0
1068
- ? insertId
1069
- : state.getIn(['scene', 'currentProjectID']);
1070
-
1071
- // Set storage data
1072
- sessionStorage.setItem('projectId', currentProjectID);
1073
- sessionStorage.setItem('email', param.email);
1074
- sessionStorage.setItem('phone', param.phone);
1075
- sessionStorage.setItem('firstName', param.firstName);
1076
- sessionStorage.setItem('lastName', param.lastName);
1077
- props.projectActions.setProjectID({ currentProjectID });
1078
- actions.userActions.login(
1079
- userData[0].id,
1080
- userData[0].role,
1081
- access_token,
1082
- utm
1083
- );
1084
- this.setState({
1085
- toolbar: this.state.toolbar,
1086
- isSaved: true,
1087
- isSnackBarOpen: true,
1088
- snackBarMessage:
1089
- 'Your project has been saved. </br> You can now request <b>Designer Assistance</b> or <b>Add to Cart</b>'
1090
- });
1091
- if (this.state.submitTosave) {
1092
- handleContinueQuote();
1093
- }
1094
- } else {
1095
- rlt.success = false;
1096
- rlt.message = message;
1097
-
1098
- this.setState({
1099
- isSnackBarOpen: true,
1100
- snackBarMessage: `Failed to add project data: ${message}`
1101
- });
1102
- }
1103
- } catch (err) {
1104
- rlt.success = false;
1105
-
1106
- console.error(err);
1107
- this.setState({
1108
- isSnackBarOpen: true,
1109
- snackBarMessage: 'Failed to add project data.'
1110
- });
1111
- }
1112
-
1113
- return rlt;
1114
- };
1115
-
1116
- let pidSplit = userInfo.pid && userInfo.pid.indexOf('?');
1117
- // If pidSplit is undefined pid is undefined
1118
- let pid =
1119
- pidSplit === undefined || pidSplit === -1
1120
- ? userInfo.pid
1121
- : userInfo.pid.slice(0, pidSplit);
1122
-
1123
- let submitForQuote = async param => {
1124
- let rlt = { success: false };
1125
-
1126
- if (!userInfo.token) {
1127
- this.setState({
1128
- isSnackBarOpen: true,
1129
- snackBarMessage: 'You should save the project first.'
1130
- });
1131
- return;
1132
- }
1133
- let apiUrl = '';
1134
- if (param.flag === constants.SUBMIT_REQUEST_ASSIST) {
1135
- apiUrl = `${API_SERVER_URL}/api/project/submitProject`;
1136
- } else if (param.flag === constants.SUBMIT_ADD_CART) {
1137
- apiUrl = `${API_SERVER_URL}/api/project/addCart`;
1138
- }
1139
- try {
1140
- const extraFormData = {
1141
- userType: sessionStorage.getItem('user_type') || '',
1142
- designType: sessionStorage.getItem('project_type') || '',
1143
- startTime: sessionStorage.getItem('project_timeline') || ''
1144
- };
1145
-
1146
- const originalAccessToken = ls.get(LOCAL_STORAGE_ORIGINAL_TOKEN);
1147
- const tokenName = ls.get(LOCAL_STORAGE_TOKEN_NAME);
1148
-
1149
- const customerRequests = param.customer_requests;
1150
- const notes = customerRequests.notes;
1151
- const response = await axios.post(apiUrl, {
1152
- access_token: userInfo.token,
1153
- data: {
1154
- ...param,
1155
- ...(extraFormData.userType
1156
- ? { user_type: extraFormData.userType }
1157
- : undefined),
1158
- ...(extraFormData.designType
1159
- ? { project_type: extraFormData.designType }
1160
- : undefined),
1161
- ...(extraFormData.startTime
1162
- ? { project_timeline: extraFormData.startTime }
1163
- : undefined),
1164
- client_name: sessionStorage.getItem('visualizerName'),
1165
- user_token: ls.get(LOCAL_STORAGE_TOKEN_VALUE),
1166
- cart_action_type: ls.get(LOCAL_STORAGE_CART_ACTION),
1167
- customer_requests: Object.values(customerRequests.reviewOptions)
1168
- .filter(Boolean)
1169
- .join(', '),
1170
- ...(param.flag === constants.SUBMIT_ADD_CART
1171
- ? {
1172
- cart_notes: notes
1173
- }
1174
- : {
1175
- designer_notes: notes
1176
- }),
1177
- question_add_to_cart: param.flag === constants.SUBMIT_ADD_CART,
1178
- ...(originalAccessToken
1179
- ? { original_token: originalAccessToken }
1180
- : undefined),
1181
- ...(tokenName
1182
- ? { query_params_token_prefix: tokenName }
1183
- : undefined)
1184
- },
1185
- num: true,
1186
- projectid: pid,
1187
- search: this.props.location.search,
1188
- userrole: userInfo.role,
1189
- url: window.location.hostname
1190
- });
1191
-
1192
- const { success, message, redirect_url } = response.data;
1193
- if (success) {
1194
- rlt.success = true;
1195
-
1196
- param.email && sessionStorage.setItem('email', param.email);
1197
- param.phone && sessionStorage.setItem('phone', param.phone);
1198
- this.setState({
1199
- redirectURL: redirect_url,
1200
- isSnackBarOpen: true,
1201
- snackBarMessage: `${
1202
- param.flag === constants.SUBMIT_REQUEST_ASSIST
1203
- ? 'Project submitted'
1204
- : 'Added to cart'
1205
- } successfully.${
1206
- customerRequests.reviewOptions.length > 0 ||
1207
- customerRequests.notes
1208
- ? ' <br /> A confirmation has been emailed to you and a designer will be in contact shortly'
1209
- : ''
1210
- }`,
1211
- isSnackBar1Open: param.flag === constants.SUBMIT_ADD_CART
1212
- });
1213
- } else {
1214
- rlt.success = false;
1215
- rlt.message = message;
1216
-
1217
- this.setState({
1218
- isSnackBarOpen: true,
1219
- snackBarMessage: `${
1220
- param.flag === constants.SUBMIT_REQUEST_ASSIST
1221
- ? 'Submitting project'
1222
- : 'Adding to cart'
1223
- } failed: ${message}`
1224
- });
1225
- }
1226
- } catch (err) {
1227
- rlt.success = false;
1228
-
1229
- console.log('err', err);
1230
- this.setState({
1231
- isSnackBarOpen: true,
1232
- snackBarMessage: `${
1233
- param.flag === constants.SUBMIT_REQUEST_ASSIST
1234
- ? 'Submitting project'
1235
- : 'Adding to cart'
1236
- } failed.`
1237
- });
1238
- }
1239
-
1240
- return rlt;
1241
- };
1242
-
1243
- return (
1244
- <section>
1245
- <SnackBar
1246
- isOpen={this.state.isSnackBarOpen}
1247
- message={this.state.snackBarMessage}
1248
- handleClose={() =>
1249
- this.setState({ isSnackBarOpen: false, snackBarMessage: '' })
1250
- }
1251
- autoHideDuration={10000}
1252
- />
1253
- <SnackBar
1254
- style={{ marginTop: this.state.isSnackBarOpen ? 75 : 'unset' }}
1255
- isOpen={this.state.isSnackBar1Open}
1256
- message={`The items in your design have been added to your shopping cart at ${CLIENTS_NAME[sessionStorage.getItem('visualizerName')]}. <br />Please log in with the same email address.`}
1257
- autoHideDuration={20000}
1258
- action={
1259
- <div>
1260
- <a
1261
- href={this.state.redirectURL}
1262
- target="_blank"
1263
- style={{
1264
- fontFamily: DEFAULT_FONT_FAMILY,
1265
- color: PRIMARY_GREEN_COLOR,
1266
- fontWeight: 700,
1267
- marginRight: 10
1268
- }}
1269
- >
1270
- View Cart
1271
- </a>
1272
- <img
1273
- onClick={() => this.setState({ isSnackBar1Open: false })}
1274
- style={{ float: 'right', height: 24, cursor: 'pointer' }}
1275
- src="/assets/img/svg/close.svg"
1276
- />
1277
- </div>
1278
- }
1279
- />
1280
- <div style={{ ...wrapperStyle, height }}>
1281
- <Header
1282
- isTokenPresent={!!this.props.match.params.token}
1283
- isSaved={this.state.isSaved}
1284
- width={headerW}
1285
- height={headerH}
1286
- state={extractedState}
1287
- reviewQuoteHandler={this.onReviewQuoteClicked.bind(this)}
1288
- handleSaveDesign={this.handleSaveDesign.bind(this)}
1289
- handleSubmitForQuote={this.handleSubmitForQuote.bind(this)}
1290
- handleNewProject={this.handleNewProject.bind(this)}
1291
- handleSubmitPrompt={submitType => {
1292
- this.setState({ submitPromptVisible: true });
1293
- this.setState({ stateSubmitType: submitType });
1294
- }}
1295
- logoImage={this.props.logoImage}
1296
- companyURL={this.props.companyURL}
1297
- setToolbar={this.setToolbar}
1298
- saveProject={saveProject}
1299
- newProject={newProject}
1300
- isModalVisible={this.state.isModalVisible}
1301
- allVisible={allVisible}
1302
- wizardStepOpend={firstVisit}
1303
- {...props}
1304
- />
1305
- {signOpen && (
1306
- <Sign
1307
- setSignOpen={this.setSignOpen.bind(this)}
1308
- setMyProjectsOpen={this.setMyProjectsOpen.bind(this)}
1309
- setMyProjectsToLogin={this.setMyProjectsToLogin.bind(this)}
1310
- myProjectsToLogin={myProjectsToLogin}
1311
- />
1312
- )}
1313
- {!allVisible && (
1314
- // left side bar & top tools bar
1315
- <Toolbar
1316
- width={toolbarW}
1317
- content={contentW}
1318
- height={toolbarH}
1319
- headerH={headerH}
1320
- state={extractedState}
1321
- layers={extractedState.scene.layers}
1322
- selectedLayer={extractedState.scene.selectedLayer}
1323
- {...props}
1324
- handleSaveDesign={this.handleSaveDesign.bind(this)}
1325
- handleSubmitForQuote={this.handleSubmitForQuote.bind(this)}
1326
- handleNewProject={this.handleNewProject.bind(this)}
1327
- handleSubmitPrompt={submitType => {
1328
- this.setState({ submitPromptVisible: true });
1329
- this.setState({
1330
- stateSubmitType: submitType
1331
- });
1332
- }}
1333
- toolBar={this.state.toolbar}
1334
- setToolbar={this.setToolbar}
1335
- setDownloadPopupVisible={this.setDownloadPopupVisible.bind(this)}
1336
- openFloor={this.openFloor}
1337
- openCabinet={this.openCabinet}
1338
- openAppliance={this.openAppliance}
1339
- openFinishing={this.openFinishing}
1340
- closeFloorTB={this.closeFloorTB}
1341
- closeCabinetTB={this.closeCabinetTB}
1342
- closeFinishingTB={this.closeFinishingTB}
1343
- closeApplianceTB={this.closeApplianceTB}
1344
- setShowProperty={this.setShowProperty}
1345
- reviewQuotePopupOpened={this.state.reviewQuotePopupOpened}
1346
- isShowProperty={this.state.isShowProperty}
1347
- categoryData={this.props.categoryData}
1348
- floorOpened={this.state.floorOpened}
1349
- cabinetOpened={this.state.cabinetOpened}
1350
- applianceOpened={this.state.applianceOpened}
1351
- finishingOpened={this.state.finishingOpened}
1352
- doorStyleOpen={this.state.doorStyleOpen}
1353
- toggleDoorStyle={this.toggleDoorStyle}
1354
- onReviewQuoteClicked={this.onReviewQuoteClicked}
1355
- wizardStepOpend={firstVisit}
1356
- replaceCabinetFlag={this.state.replaceCabinetFlag}
1357
- replaceCabinet={this.replaceCabinet}
1358
- />
1359
- )}
1360
- <Content
1361
- width={contentW}
1362
- height={contentH}
1363
- catalog={this.props.catalog}
1364
- state={extractedState}
1365
- toolBar={this.state.toolbar}
1366
- setToolbar={this.setToolbar}
1367
- replaceCabinet={this.replaceCabinet}
1368
- keyDownEnable={
1369
- !savePopupVisible && !quotePopupVisible && !assistPopupVisible
1370
- }
1371
- {...props}
1372
- onWheel={event => event.preventDefault()}
1373
- />
1374
- {!allVisible && (
1375
- <FooterBar
1376
- content={contentW}
1377
- setToolbar={this.setToolbar}
1378
- layers={extractedState.scene.layers}
1379
- setShowProperty={this.setShowProperty}
1380
- state={extractedState}
1381
- selectedLayer={extractedState.scene.selectedLayer}
1382
- {...props}
1383
- />
1384
- )}
1385
- {firstVisit && (
1386
- <WizardStep
1387
- key="first-setting"
1388
- content={contentW}
1389
- layers={extractedState.scene.layers}
1390
- close={() => this.setState({ wizardStepOpend: false })}
1391
- state={extractedState}
1392
- setMyProjectsToLogin={this.setMyProjectsToLogin.bind(this)}
1393
- setSignOpen={this.setSignOpen.bind(this)}
1394
- selectedLayer={extractedState.scene.selectedLayer}
1395
- setMyProjectsOpen={this.setMyProjectsOpen.bind(this)}
1396
- {...props}
1397
- />
1398
- )}
1399
- {myProjectsOpen && (
1400
- <MyProjects
1401
- setMyProjectsOpen={this.setMyProjectsOpen.bind(this)}
1402
- {...props}
1403
- />
1404
- )}
1405
- <SaveDesignPopup
1406
- visible={savePopupVisible}
1407
- submitTosave={submitTosave}
1408
- handleSaveDesign={this.handleSaveDesign.bind(this)}
1409
- saveProject={saveProject}
1410
- state={extractedState}
1411
- {...props}
1412
- />
1413
- <SubmitForQuotePopup
1414
- categoryData={categoryData}
1415
- curDoorStyle={doorStyle}
1416
- handleSubmitForQuote={this.handleSubmitForQuote.bind(this)}
1417
- submitForQuote={submitForQuote}
1418
- visible={quotePopupVisible}
1419
- setDoorStyle={this.props.itemsActions.setDoorStyle}
1420
- submitType={stateSubmitType}
1421
- {...props}
1422
- />
1423
- <NewProjectPopup
1424
- isSaved={this.state.isSaved}
1425
- visible={newProjectPopupVisible}
1426
- handleNewProject={this.handleNewProject.bind(this)}
1427
- newProject={newProject}
1428
- areas={extractedState.getIn([
1429
- 'scene',
1430
- 'layers',
1431
- extractedState.scene.selectedLayer,
1432
- 'areas'
1433
- ])}
1434
- />
1435
- <SubmitPromptPopup
1436
- visible={submitPromptVisible}
1437
- submitType={stateSubmitType}
1438
- handleOk={value =>
1439
- this.handleSaveDesign(value) ||
1440
- this.setState({ submitTosave: true })
1441
- }
1442
- handleClose={() => {
1443
- this.setState({ submitPromptVisible: false });
1444
- }}
1445
- />
1446
- <AutosavePromptPopup
1447
- isLeaving={isLeaving}
1448
- visible={savePromptVisible}
1449
- handleOk={this.handleSaveDesign.bind(this)}
1450
- handleClose={() =>
1451
- this.setState({ savePromptVisible: false, submitTosave: false })
1452
- }
1453
- />
1454
- <DownloadSummaryPopup
1455
- visible={downloadPopupVisible}
1456
- state={extractedState}
1457
- catalog={this.props.catalog}
1458
- setDownloadPopupVisible={this.setDownloadPopupVisible.bind(this)}
1459
- {...props}
1460
- />
1461
- {saveAlert}
1462
- </div>
1463
- </section>
1464
- );
1465
- }
1466
- }
1467
-
1468
- KitchenConfigurator.propTypes = {
1469
- translator: PropTypes.instanceOf(Translator),
1470
-
1471
- catalog: PropTypes.instanceOf(Catalog),
1472
- allowProjectFileSupport: PropTypes.bool,
1473
- plugins: PropTypes.arrayOf(PropTypes.func),
1474
- autosaveKey: PropTypes.string,
1475
- autosaveDelay: PropTypes.number,
1476
- width: PropTypes.number.isRequired,
1477
- height: PropTypes.number.isRequired,
1478
- stateExtractor: PropTypes.func.isRequired,
1479
- toolbarButtons: PropTypes.array,
1480
- sidebarComponents: PropTypes.array,
1481
- footerbarComponents: PropTypes.array,
1482
- customContents: PropTypes.object,
1483
- softwareSignature: PropTypes.string,
1484
- configData: PropTypes.object
1485
- };
1486
-
1487
- KitchenConfigurator.contextTypes = {
1488
- store: PropTypes.object.isRequired
1489
- };
1490
-
1491
- KitchenConfigurator.childContextTypes = {
1492
- ...objectsMap(actions, () => PropTypes.object),
1493
- translator: PropTypes.object,
1494
- catalog: PropTypes.object
1495
- };
1496
-
1497
- KitchenConfigurator.defaultProps = {
1498
- translator: new Translator(),
1499
- catalog: new Catalog(),
1500
- plugins: [],
1501
- allowProjectFileSupport: true,
1502
- softwareSignature: `KitchenConfigurator ${VERSION}`,
1503
- toolbarButtons: [],
1504
- sidebarComponents: [],
1505
- footerbarComponents: [],
1506
- customContents: {},
1507
- configData: {}
1508
- };
1509
-
1510
- //redux connect
1511
- function mapStateToProps(reduxState) {
1512
- return {
1513
- state: reduxState
1514
- };
1515
- }
1516
-
1517
- function mapDispatchToProps(dispatch) {
1518
- return objectsMap(actions, actionNamespace =>
1519
- bindActionCreators(actions[actionNamespace], dispatch)
1520
- );
1521
- }
1522
-
1523
- export default connect(
1524
- mapStateToProps,
1525
- mapDispatchToProps
1526
- )(KitchenConfigurator);