kitchen-simulator 5.0.0-test.18 → 5.0.0-test.19

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 (179) hide show
  1. package/package.json +8 -26
  2. package/src/@history.js +3 -0
  3. package/src/CrossSignOn.jsx +94 -0
  4. package/src/KitchenConfigurator.jsx +1526 -0
  5. package/src/KitchenConfiguratorApp.jsx +1 -1
  6. package/src/_KitchenConfigurator.jsx +3 -3
  7. package/src/components/catalog-view/catalog-breadcrumb.jsx +53 -0
  8. package/src/components/catalog-view/catalog-item.jsx +229 -0
  9. package/src/components/catalog-view/catalog-list.jsx +173 -0
  10. package/src/components/catalog-view/catalog-page-item.jsx +110 -0
  11. package/src/components/catalog-view/catalog-turn-back-page-item.jsx +80 -0
  12. package/src/components/configurator/custom-configurator.jsx +77 -0
  13. package/src/components/configurator/project-configurator.jsx +120 -0
  14. package/src/components/export.js +36 -0
  15. package/src/components/firstsetting/button/styles.js +223 -0
  16. package/src/components/firstsetting/export.js +9 -0
  17. package/src/components/firstsetting/firstsetting-content-button.jsx +198 -0
  18. package/src/components/firstsetting/firstsetting-toggle-button.jsx +101 -0
  19. package/src/components/firstsetting/firstsetting.jsx +814 -0
  20. package/src/components/footerbar/button/ControlButton.jsx +43 -0
  21. package/src/components/footerbar/button/DirectionButton.jsx +54 -0
  22. package/src/components/footerbar/button/DirectionPanSpinButton.jsx +36 -0
  23. package/src/components/footerbar/button/ToggleButton.jsx +58 -0
  24. package/src/components/footerbar/button/ToggleConvertButton.jsx +48 -0
  25. package/src/components/footerbar/button/ToggleMeasureButton.jsx +33 -0
  26. package/src/components/footerbar/button/styles.js +217 -0
  27. package/src/components/footerbar/export.js +9 -0
  28. package/src/components/footerbar/footer-content-button.jsx +198 -0
  29. package/src/components/footerbar/footer-toggle-button.jsx +101 -0
  30. package/src/components/footerbar/footerbar.jsx +1103 -0
  31. package/src/components/footerbar/styles.js +263 -0
  32. package/src/components/header/button/MenuButton.jsx +46 -0
  33. package/src/components/header/button/SaveButton.jsx +54 -0
  34. package/src/components/header/button/styles.js +181 -0
  35. package/src/components/header/export.js +5 -0
  36. package/src/components/header/header.jsx +631 -0
  37. package/src/components/header/header.style.css +47 -0
  38. package/src/components/header/styles.js +320 -0
  39. package/src/components/login/Login.js +77 -0
  40. package/src/components/login/LoginForm/index.js +108 -0
  41. package/src/components/login/Register.js +82 -0
  42. package/src/components/login/RegisterForm/index.js +171 -0
  43. package/src/components/login/jwtService.js +201 -0
  44. package/src/components/login/style.css +158 -0
  45. package/src/components/login/style.scss +260 -0
  46. package/src/components/myprojects/export.js +5 -0
  47. package/src/components/myprojects/index.jsx +445 -0
  48. package/src/components/myprojects/styles.js +241 -0
  49. package/src/components/sidebar/custom-accordion.jsx +48 -0
  50. package/src/components/sidebar/export.js +15 -0
  51. package/src/components/sidebar/panel-element-editor/attributes-editor/attributes-editor.jsx +73 -0
  52. package/src/components/sidebar/panel-element-editor/attributes-editor/confirm-popup.jsx +101 -0
  53. package/src/components/sidebar/panel-element-editor/attributes-editor/hole-attributes-editor.jsx +149 -0
  54. package/src/components/sidebar/panel-element-editor/attributes-editor/item-attributes-editor.jsx +316 -0
  55. package/src/components/sidebar/panel-element-editor/attributes-editor/line-attributes-editor.jsx +108 -0
  56. package/src/components/sidebar/panel-element-editor/element-editor.jsx +1070 -0
  57. package/src/components/sidebar/panel-element-editor/multi-elements-editor.jsx +0 -0
  58. package/src/components/sidebar/panel-element-editor/panel-element-editor.jsx +104 -0
  59. package/src/components/sidebar/panel-element-editor/panel-multi-elements-editor.jsx +155 -0
  60. package/src/components/sidebar/panel-group-editor.jsx +272 -0
  61. package/src/components/sidebar/panel-groups.jsx +310 -0
  62. package/src/components/sidebar/panel-guides.jsx +192 -0
  63. package/src/components/sidebar/panel-layer-elements.jsx +298 -0
  64. package/src/components/sidebar/panel-layers.jsx +381 -0
  65. package/src/components/sidebar/panel.jsx +71 -0
  66. package/src/components/sidebar/sidebar.jsx +106 -0
  67. package/src/components/sidebar/toolbar-panel.jsx +139 -0
  68. package/src/components/sign/export.js +7 -0
  69. package/src/components/sign/main/index.jsx +523 -0
  70. package/src/components/sign/main/styles.js +163 -0
  71. package/src/components/toolbar/button/ControlButton.jsx +41 -0
  72. package/src/components/toolbar/button/DirectionButton.jsx +34 -0
  73. package/src/components/toolbar/button/RightButton.jsx +103 -0
  74. package/src/components/toolbar/button/ToggleButton.jsx +41 -0
  75. package/src/components/toolbar/button/index.jsx +55 -0
  76. package/src/components/toolbar/button/styles.js +127 -0
  77. package/src/components/toolbar/components/DoorStyleMenu.jsx +103 -0
  78. package/src/components/toolbar/components/Pricing.jsx +126 -0
  79. package/src/components/toolbar/components/ReviewForQuote.jsx +635 -0
  80. package/src/components/toolbar/export.js +21 -0
  81. package/src/components/toolbar/main/Alert.js +122 -0
  82. package/src/components/toolbar/main/TakePictureModal.jsx +104 -0
  83. package/src/components/toolbar/main/confirm-popup.jsx +99 -0
  84. package/src/components/toolbar/main/index.jsx +5627 -0
  85. package/src/components/toolbar/main/lShaped.json +311 -0
  86. package/src/components/toolbar/main/longNarrow.json +238 -0
  87. package/src/components/toolbar/main/myComponents.js +123 -0
  88. package/src/components/toolbar/main/oRectangle.json +220 -0
  89. package/src/components/toolbar/main/rectangle.json +238 -0
  90. package/src/components/toolbar/main/style.css +107 -0
  91. package/src/components/toolbar/main/styles.js +696 -0
  92. package/src/components/toolbar/plugin-item.jsx +123 -0
  93. package/src/components/toolbar/popup/appliance/appliance-category/index.jsx +73 -0
  94. package/src/components/toolbar/popup/appliance/choose-appliance/index.jsx +102 -0
  95. package/src/components/toolbar/popup/appliance/index.jsx +83 -0
  96. package/src/components/toolbar/popup/autosaveprompt/index.jsx +150 -0
  97. package/src/components/toolbar/popup/autosaveprompt/styles.css +64 -0
  98. package/src/components/toolbar/popup/autosaveprompt/styles.js +40 -0
  99. package/src/components/toolbar/popup/cabinet/cabinet-category/index.jsx +73 -0
  100. package/src/components/toolbar/popup/cabinet/choose-product/index.jsx +119 -0
  101. package/src/components/toolbar/popup/cabinet/index.jsx +85 -0
  102. package/src/components/toolbar/popup/doorStyle/choose-style/index.jsx +63 -0
  103. package/src/components/toolbar/popup/doorStyle/index.jsx +71 -0
  104. package/src/components/toolbar/popup/doorStyle/style-category/index.jsx +139 -0
  105. package/src/components/toolbar/popup/downloadsummary/downloadSummaryContext.js +2 -0
  106. package/src/components/toolbar/popup/downloadsummary/downloadSummaryTemp.jsx +157 -0
  107. package/src/components/toolbar/popup/downloadsummary/index.jsx +643 -0
  108. package/src/components/toolbar/popup/downloadsummary/show2D/show2DView.jsx +51 -0
  109. package/src/components/toolbar/popup/downloadsummary/show2D/viewer2DDownLoad.jsx +175 -0
  110. package/src/components/toolbar/popup/downloadsummary/show3D/show3DView.jsx +283 -0
  111. package/src/components/toolbar/popup/downloadsummary/show3D/viewer3DDownLoad.jsx +2257 -0
  112. package/src/components/toolbar/popup/downloadsummary/showCabinetInfo.js +93 -0
  113. package/src/components/toolbar/popup/downloadsummary/showElevation/showElevationView.jsx +132 -0
  114. package/src/components/toolbar/popup/downloadsummary/showElevation/viewer3DElevationDownload.jsx +2198 -0
  115. package/src/components/toolbar/popup/downloadsummary/showElevation/viewerElevationDownload.jsx +152 -0
  116. package/src/components/toolbar/popup/downloadsummary/showWarranty.jsx +149 -0
  117. package/src/components/toolbar/popup/downloadsummary/styles.css +177 -0
  118. package/src/components/toolbar/popup/downloadsummary/styles.js +453 -0
  119. package/src/components/toolbar/popup/finishingtouch/category/index.jsx +34 -0
  120. package/src/components/toolbar/popup/finishingtouch/index.jsx +58 -0
  121. package/src/components/toolbar/popup/finishingtouch/material-edit.jsx +112 -0
  122. package/src/components/toolbar/popup/finishingtouch/product/index.jsx +116 -0
  123. package/src/components/toolbar/popup/floorplan/choose-floor/confirm-popup.jsx +101 -0
  124. package/src/components/toolbar/popup/floorplan/choose-floor/index.jsx +254 -0
  125. package/src/components/toolbar/popup/floorplan/choose-floor/lShaped.json +311 -0
  126. package/src/components/toolbar/popup/floorplan/choose-floor/longNarrow.json +238 -0
  127. package/src/components/toolbar/popup/floorplan/choose-floor/oRectangle.json +220 -0
  128. package/src/components/toolbar/popup/floorplan/choose-floor/rectangle.json +238 -0
  129. package/src/components/toolbar/popup/floorplan/choose-floor/styles.js +86 -0
  130. package/src/components/toolbar/popup/floorplan/floor-category/index.jsx +109 -0
  131. package/src/components/toolbar/popup/floorplan/index.jsx +60 -0
  132. package/src/components/toolbar/popup/index.jsx +241 -0
  133. package/src/components/toolbar/popup/newproject/index.jsx +59 -0
  134. package/src/components/toolbar/popup/newproject/styles.css +64 -0
  135. package/src/components/toolbar/popup/newproject/styles.js +41 -0
  136. package/src/components/toolbar/popup/product/appliance.jsx +54 -0
  137. package/src/components/toolbar/popup/product/cabinetproduct.jsx +15 -0
  138. package/src/components/toolbar/popup/product/doorstyle.jsx +58 -0
  139. package/src/components/toolbar/popup/product/doorstyleproduct.jsx +47 -0
  140. package/src/components/toolbar/popup/product/floor.jsx +36 -0
  141. package/src/components/toolbar/popup/product/floorproduct.jsx +42 -0
  142. package/src/components/toolbar/popup/product/index.jsx +36 -0
  143. package/src/components/toolbar/popup/product/primary.jsx +77 -0
  144. package/src/components/toolbar/popup/product/productline.jsx +93 -0
  145. package/src/components/toolbar/popup/product/reviewItem.jsx +427 -0
  146. package/src/components/toolbar/popup/product/reviewMolding.jsx +310 -0
  147. package/src/components/toolbar/popup/product/style.css +54 -0
  148. package/src/components/toolbar/popup/product/styles.js +260 -0
  149. package/src/components/toolbar/popup/savedesign/FullPictureForm.jsx +146 -0
  150. package/src/components/toolbar/popup/savedesign/index.jsx +495 -0
  151. package/src/components/toolbar/popup/savedesign/savedesign.style.css +16 -0
  152. package/src/components/toolbar/popup/savedesign/styles.js +151 -0
  153. package/src/components/toolbar/popup/setDoorStyleOption/index.jsx +87 -0
  154. package/src/components/toolbar/popup/styles.js +909 -0
  155. package/src/components/toolbar/popup/submitforquote/AddToCartOptions.jsx +192 -0
  156. package/src/components/toolbar/popup/submitforquote/CustomerRequestsForm.jsx +96 -0
  157. package/src/components/toolbar/popup/submitforquote/SkipDesignerReview.jsx +54 -0
  158. package/src/components/toolbar/popup/submitforquote/StepDots.jsx +25 -0
  159. package/src/components/toolbar/popup/submitforquote/cart-choice.jsx +116 -0
  160. package/src/components/toolbar/popup/submitforquote/doorstyle-menus.js +38 -0
  161. package/src/components/toolbar/popup/submitforquote/index.jsx +698 -0
  162. package/src/components/toolbar/popup/submitforquote/styles.css +105 -0
  163. package/src/components/toolbar/popup/submitforquote/styles.js +294 -0
  164. package/src/components/toolbar/popup/submitprompt/index.jsx +89 -0
  165. package/src/components/toolbar/popup/submitprompt/styles.css +64 -0
  166. package/src/components/toolbar/popup/submitprompt/styles.js +42 -0
  167. package/src/components/toolbar/toolbar-button.jsx +90 -0
  168. package/src/components/toolbar/toolbar-load-button.jsx +36 -0
  169. package/src/components/toolbar/toolbar-save-button.jsx +32 -0
  170. package/src/components/wizardstep/button/styles.js +677 -0
  171. package/src/components/wizardstep/export.js +5 -0
  172. package/src/components/wizardstep/index.jsx +1372 -0
  173. package/src/components/wizardstep/styles.js +688 -0
  174. package/src/components/wizardstep/wizardstep-content-button.jsx +198 -0
  175. package/src/components/wizardstep/wizardstep-toggle-button.jsx +101 -0
  176. package/src/{_index.js → index.js} +4 -4
  177. package/src/renderer.jsx +466 -0
  178. package/src/actions/_export.js +0 -35
  179. package/src/components/_export.js +0 -11
@@ -0,0 +1,1526 @@
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);