hart-estate-widget 0.0.10 → 0.0.13

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 (39) hide show
  1. package/build/api/index.js +33 -0
  2. package/build/assets/img/bricks.jpeg +0 -0
  3. package/build/assets/img/door-texture.jpeg +0 -0
  4. package/build/assets/img/door.jpeg +0 -0
  5. package/build/assets/img/exterior-wall-texture.jpeg +0 -0
  6. package/build/assets/img/floor-bathroom.jpg +0 -0
  7. package/build/assets/img/floor-dark.png +0 -0
  8. package/build/assets/img/floor-white.png +0 -0
  9. package/build/assets/img/floor.jpg +0 -0
  10. package/build/assets/img/ground.svg +9 -0
  11. package/build/assets/img/wall-texture.jpg +0 -0
  12. package/build/assets/sass/animation.sass +5 -0
  13. package/build/assets/sass/components/instructions.sass +3 -0
  14. package/build/assets/sass/components/loader.sass +2 -0
  15. package/build/assets/sass/components/model.sass +12 -0
  16. package/build/assets/sass/components/panorama.sass +4 -35
  17. package/build/assets/sass/components/tabs.sass +66 -0
  18. package/build/components/Application.js +13 -3
  19. package/build/components/ImageTab.js +3 -2
  20. package/build/components/Instructions.js +2 -0
  21. package/build/components/Loader.js +3 -2
  22. package/build/components/ModelTab.js +115 -82
  23. package/build/components/PanoramaTab.js +32 -22
  24. package/build/components/TabPanes.js +7 -2
  25. package/build/components/TabWrapper.js +2 -0
  26. package/build/components/Widget.js +17 -3
  27. package/build/config/defaultConfig.js +7 -8
  28. package/build/index.css +1 -1
  29. package/build/index.css.map +1 -1
  30. package/build/index.js +8 -0
  31. package/build/store/apiStore.js +63 -0
  32. package/build/store/houseStore.js +679 -0
  33. package/build/store/modelStore.js +228 -0
  34. package/build/utils/csg/csg-lib.js +387 -0
  35. package/build/utils/csg/csg-worker.js +94 -0
  36. package/build/utils/csg/three-csg.js +280 -0
  37. package/build/utils/modelHelpers.js +105 -35
  38. package/build/utils/panoramaHelpers.js +4 -0
  39. package/package.json +2 -5
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.loadFurnitureData = exports.STAGE_API_URL = exports.PRODUCTION_API_URL = void 0;
7
+
8
+ require("core-js/modules/es.promise.js");
9
+
10
+ require("core-js/modules/es.array.reduce.js");
11
+
12
+ var _react = _interopRequireDefault(require("react"));
13
+
14
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
+
16
+ const PRODUCTION_API_URL = 'https://backend.estate.myhart.ru';
17
+ exports.PRODUCTION_API_URL = PRODUCTION_API_URL;
18
+ const STAGE_API_URL = 'https://backend-stage.estate.myhart.ru';
19
+ exports.STAGE_API_URL = STAGE_API_URL;
20
+ const API_URL = {
21
+ 'production': PRODUCTION_API_URL,
22
+ 'stage': STAGE_API_URL
23
+ };
24
+
25
+ const loadFurnitureData = async function loadFurnitureData(furniture) {
26
+ let env = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'production';
27
+ const furnitureQuery = furniture.reduce((acc, item, i) => acc += "".concat(i === 0 ? '' : ',').concat(item.Model), '');
28
+ const path = "".concat(API_URL[env], "/api/furniture?only=").concat(furnitureQuery);
29
+ const response = await fetch(path);
30
+ return await response.json();
31
+ };
32
+
33
+ exports.loadFurnitureData = loadFurnitureData;
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,9 @@
1
+ <svg width="250" height="250" viewBox="0 0 250 250" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <rect width="125" height="125" fill="white"/>
3
+ <rect x="125" y="125" width="125" height="125" fill="white"/>
4
+ <rect y="125" width="125" height="125" fill="black"/>
5
+ <rect x="125" width="125" height="125" fill="black"/>
6
+ <rect x="124" width="2" height="250" fill="#00A3FF"/>
7
+ <rect y="126" width="2" height="250" transform="rotate(-90 0 126)" fill="#00A3FF"/>
8
+ <rect x="0.5" y="0.5" width="249" height="249" stroke="#00A3FF"/>
9
+ </svg>
@@ -0,0 +1,5 @@
1
+ @keyframes fadeIn
2
+ 0%
3
+ opacity: 0
4
+ 100%
5
+ opacity: 1
@@ -48,3 +48,6 @@
48
48
  cursor: pointer
49
49
  border: none
50
50
  padding: 10px 5px
51
+ &:disabled
52
+ opacity: .75
53
+ cursor: not-allowed
@@ -10,6 +10,8 @@
10
10
  left: 50%
11
11
  top: 50%
12
12
  transform: translate(-50%, -50%)
13
+ &--sm
14
+ transform: translate(-50%, -50%) scale(.75)
13
15
  div
14
16
  position: absolute
15
17
  top: 33px
@@ -12,3 +12,15 @@
12
12
  width: 100%
13
13
  height: 100%
14
14
  display: block
15
+ &-joystick
16
+ position: absolute
17
+ left: 100px
18
+ bottom: 100px
19
+ opacity: 0
20
+ pointer-events: none
21
+ @media #{$mobile}
22
+ left: 50%
23
+ transform: translateX(-50%)
24
+ &--active
25
+ opacity: 1
26
+ pointer-events: unset
@@ -35,11 +35,15 @@
35
35
  right: 15px
36
36
  bottom: 70px
37
37
  z-index: 10000
38
+ &--hidden
39
+ display: none !important
38
40
  img
39
41
  width: 100px
40
42
  border-radius: 10px
43
+ cursor: zoom-in
41
44
  &.active
42
45
  width: 240px
46
+ cursor: zoom-out
43
47
  &:hover
44
48
  box-shadow: 1px 1px 10px rgba(0,0,0,0.15)
45
49
  &__dot
@@ -61,38 +65,3 @@
61
65
  &--active
62
66
  background-color: red
63
67
  border: 2px solid red
64
- &-menu
65
- position: absolute
66
- z-index: 3
67
- left: 15px
68
- top: 15px
69
- max-height: 100%
70
- overflow-y: auto
71
- padding-bottom: 30px
72
- ul
73
- list-style-type: none
74
- li
75
- color: $black
76
- background-color: $mainColor
77
- padding: 5px 15px
78
- border-radius: 10px
79
- font-size: .8rem
80
- border: none
81
- cursor: pointer
82
- margin-bottom: 15px
83
- width: 150px
84
- @include noSelect
85
- &:hover
86
- box-shadow: 1px 1px 10px rgba(0, 0, 0, .15)
87
- &:nth-child(1)
88
- position: relative
89
- &::after
90
- content: '|||'
91
- transform: translateY(-50%) rotate(90deg)
92
- font-size: 20px
93
- line-height: 20px
94
- margin-left: 10px
95
- display: block
96
- position: absolute
97
- right: 10px
98
- top: 50%
@@ -48,6 +48,72 @@
48
48
  height: 100%
49
49
  object-fit: cover
50
50
 
51
+ &-menu
52
+ position: absolute
53
+ z-index: 3
54
+ left: 15px
55
+ top: 15px
56
+ max-height: 100%
57
+ overflow-y: auto
58
+ padding-bottom: 30px
59
+ &__wallpapers
60
+ display: flex
61
+ flex-wrap: wrap
62
+ align-items: flex-start
63
+ margin-top: 10px
64
+ width: 100%
65
+ img
66
+ width: 30px
67
+ height: 30px
68
+ display: block
69
+ object-fit: cover
70
+ cursor: pointer
71
+ margin-right: 10px
72
+ margin-block-end: 10px
73
+ ul
74
+ list-style-type: none
75
+ li
76
+ color: $black
77
+ background-color: $mainColor
78
+ padding: 5px 15px
79
+ border-radius: 10px
80
+ font-size: .8rem
81
+ border: none
82
+ cursor: pointer
83
+ margin-bottom: 15px
84
+ width: 200px
85
+ @include noSelect
86
+ label
87
+ display: flex
88
+ cursor: inherit
89
+ width: 100%
90
+ input
91
+ &[type=color]
92
+ cursor: pointer
93
+ margin-left: auto
94
+ width: 50px
95
+ height: 20px
96
+ border: 0
97
+ border-radius: 5px
98
+ &::-webkit-color-swatch-wrapper
99
+ display: none !important
100
+ &[type=file]
101
+ display: none
102
+ &:hover
103
+ box-shadow: 1px 1px 10px rgba(0, 0, 0, .15)
104
+ &:nth-child(1)
105
+ position: relative
106
+ &::after
107
+ content: '|||'
108
+ transform: translateY(-50%) rotate(90deg)
109
+ font-size: 20px
110
+ line-height: 20px
111
+ margin-left: 10px
112
+ display: block
113
+ position: absolute
114
+ right: 10px
115
+ top: 50%
116
+
51
117
  .widget-tab-panes
52
118
  position: absolute
53
119
  z-index: 3
@@ -50,16 +50,20 @@ const Application = (0, _mobxReactLite.observer)(_ref => {
50
50
 
51
51
  const tabsList = {
52
52
  'planImage': /*#__PURE__*/_react.default.createElement(_ImageTab.default, {
53
- image: config.planImage
53
+ image: config.planImage,
54
+ alt: "plan-view"
54
55
  }),
55
56
  'topView': /*#__PURE__*/_react.default.createElement(_ImageTab.default, {
56
- image: config.topView
57
+ image: config.topView,
58
+ alt: "top-view"
57
59
  }),
58
60
  'topDownView': /*#__PURE__*/_react.default.createElement(_ImageTab.default, {
59
- image: config.topDownView
61
+ image: config.topDownView,
62
+ alt: "top-down-view"
60
63
  }),
61
64
  'rotation': /*#__PURE__*/_react.default.createElement(_TabWrapper.default, {
62
65
  isActive: !isTabPanesVisible,
66
+ disabled: !config.rotationImages[0],
63
67
  image: config.rotationImages[0],
64
68
  title: "360\xB0 overview",
65
69
  text: ['Use mouse to rotate', 'Shift + LMB to move'],
@@ -69,6 +73,7 @@ const Application = (0, _mobxReactLite.observer)(_ref => {
69
73
  })),
70
74
  'panorama': /*#__PURE__*/_react.default.createElement(_TabWrapper.default, {
71
75
  isActive: !isTabPanesVisible,
76
+ disabled: !config.panoramaImages[0],
72
77
  image: config.panoramaImages[0],
73
78
  title: "Panoramic tour",
74
79
  text: ['Use mouse to rotate', 'To move through the rooms, click on the layout thumbnail'],
@@ -80,6 +85,7 @@ const Application = (0, _mobxReactLite.observer)(_ref => {
80
85
  })),
81
86
  'model': /*#__PURE__*/_react.default.createElement(_TabWrapper.default, {
82
87
  isActive: !isTabPanesVisible,
88
+ disabled: !config.json,
83
89
  image: _D.default,
84
90
  title: "3D Model",
85
91
  text: ['Use mouse to rotate', 'Use the right mouse button to move'],
@@ -101,6 +107,10 @@ const Application = (0, _mobxReactLite.observer)(_ref => {
101
107
  window.addEventListener('resize', setWindowHeight);
102
108
  setWindowHeight();
103
109
  }, []);
110
+ (0, _react.useEffect)(() => {
111
+ if (config.tabs.some(tab => tab === currentTab)) return;
112
+ setCurrentTab(config.tabs[0]);
113
+ }, [config, currentTab]);
104
114
  return /*#__PURE__*/_react.default.createElement("main", {
105
115
  className: "widget-application",
106
116
  style: appStyle
@@ -11,12 +11,13 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
11
11
 
12
12
  const ImageTab = _ref => {
13
13
  let {
14
- image
14
+ image,
15
+ alt
15
16
  } = _ref;
16
17
  return /*#__PURE__*/_react.default.createElement("img", {
17
18
  className: "widget-tab__image",
18
19
  src: image,
19
- alt: "plan-view"
20
+ alt: alt
20
21
  });
21
22
  };
22
23
 
@@ -13,6 +13,7 @@ const Instructions = _ref => {
13
13
  let {
14
14
  title,
15
15
  text,
16
+ disabled,
16
17
  onClick
17
18
  } = _ref;
18
19
  return /*#__PURE__*/_react.default.createElement("div", {
@@ -28,6 +29,7 @@ const Instructions = _ref => {
28
29
  }, row))), /*#__PURE__*/_react.default.createElement("div", {
29
30
  className: "widget-instructions__footer"
30
31
  }, /*#__PURE__*/_react.default.createElement("button", {
32
+ disabled: disabled,
31
33
  onClick: onClick,
32
34
  type: "button"
33
35
  }, "Start"))));
@@ -11,10 +11,11 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
11
11
 
12
12
  const Loader = _ref => {
13
13
  let {
14
- absolute
14
+ absolute,
15
+ size = 'lg'
15
16
  } = _ref;
16
17
  return /*#__PURE__*/_react.default.createElement("div", {
17
- className: "widget-loader ".concat(absolute ? 'widget-loader--absolute' : '')
18
+ className: "widget-loader widget-loader--".concat(size, " ").concat(absolute ? 'widget-loader--absolute' : '')
18
19
  }, /*#__PURE__*/_react.default.createElement("div", null), /*#__PURE__*/_react.default.createElement("div", null), /*#__PURE__*/_react.default.createElement("div", null), /*#__PURE__*/_react.default.createElement("div", null));
19
20
  };
20
21
 
@@ -9,13 +9,13 @@ require("core-js/modules/web.dom-collections.iterator.js");
9
9
 
10
10
  var _react = _interopRequireWildcard(require("react"));
11
11
 
12
- var THREE = _interopRequireWildcard(require("three"));
12
+ var _mobxReactLite = require("mobx-react-lite");
13
13
 
14
- var _cameraControls = _interopRequireDefault(require("camera-controls"));
14
+ var _modelStore = _interopRequireDefault(require("../store/modelStore"));
15
15
 
16
16
  var _modelHelpers = require("../utils/modelHelpers");
17
17
 
18
- var _grass = _interopRequireDefault(require("../assets/img/grass.png"));
18
+ var _nipplejs = _interopRequireDefault(require("nipplejs"));
19
19
 
20
20
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
21
21
 
@@ -23,93 +23,126 @@ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "functio
23
23
 
24
24
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
25
25
 
26
- _cameraControls.default.install({
27
- THREE: THREE
28
- });
29
-
30
- const textureLoader = new THREE.TextureLoader();
31
-
32
- const createScene = () => {
33
- const scene = new THREE.Scene();
34
- const light = new THREE.AmbientLight(0xffffff);
35
- scene.background = new THREE.Color('#FAFAFA');
36
- scene.add(light);
37
- createGround(scene);
38
- return scene;
39
- };
40
-
41
- const createCamera = renderer => {
42
- const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
43
- camera.position.set(0, 0, 0);
44
- window.addEventListener('resize', () => {
45
- camera.aspect = window.innerWidth / window.innerHeight;
46
- camera.updateProjectionMatrix();
47
- renderer.setSize(window.innerWidth, window.innerHeight);
48
- });
49
- return camera;
50
- };
51
-
52
- const createRenderer = () => {
53
- const renderer = new THREE.WebGLRenderer();
54
- renderer.setPixelRatio(window.devicePixelRatio);
55
- renderer.setSize(window.innerWidth, window.innerHeight);
56
- renderer.localClippingEnabled = true;
57
- return renderer;
58
- };
59
-
60
- const createControls = (clock, camera, scene, renderer) => {
61
- const controls = new _cameraControls.default(camera, renderer.domElement);
62
- controls.minDistance = 0.5;
63
- controls.maxDistance = 180;
64
- controls.maxPolarAngle = Math.PI / 2.1;
65
- (0, _modelHelpers.setDefaultControls)(controls, Math.PI / 4);
66
- controls.verticalDragToForward = true;
67
- (0, _modelHelpers.addKeyboardControls)(controls);
68
-
69
- const animate = () => {
70
- controls.update(clock.getDelta());
71
- window.requestAnimationFrame(animate);
72
- renderer.render(scene, camera);
73
- };
74
-
75
- animate();
76
- return controls;
77
- };
78
-
79
- const createGround = scene => {
80
- textureLoader.load(_grass.default, grassTexture => {
81
- grassTexture.wrapS = grassTexture.wrapT = THREE.RepeatWrapping;
82
- grassTexture.repeat.set(70, 70);
83
- let groundMaterial = new THREE.MeshBasicMaterial({
84
- map: grassTexture,
85
- color: 'rgb(255,255,255)'
86
- });
87
- let groundMesh = new THREE.Mesh(new THREE.PlaneBufferGeometry(500, 500), groundMaterial);
88
- groundMesh.rotation.x = -Math.PI / 2;
89
- scene.add(groundMesh);
90
- });
91
- };
92
-
93
- const ModelTab = _ref => {
26
+ const ModelTab = (0, _mobxReactLite.observer)(_ref => {
94
27
  let {
95
28
  json
96
29
  } = _ref;
97
- const [clock] = (0, _react.useState)(new THREE.Clock());
98
- const [scene] = (0, _react.useState)(createScene());
99
- const [renderer] = (0, _react.useState)(createRenderer());
100
- const [camera] = (0, _react.useState)(createCamera(renderer));
101
- const [controls] = (0, _react.useState)(createControls(clock, camera, scene, renderer));
30
+ const [menuState, setMenuState] = (0, _react.useState)(false);
31
+ const {
32
+ houseStore
33
+ } = _modelStore.default;
102
34
  (0, _react.useEffect)(() => {
103
35
  const container = document.querySelector('.widget-tab__model-scene');
104
- if (container.children.length !== 0) return;
105
- container.appendChild(renderer.domElement);
106
- }, [renderer]);
36
+ container.appendChild(_modelStore.default.renderer.domElement);
37
+
38
+ _modelStore.default.setCurrentControlsType('orbit');
39
+
40
+ if (_modelStore.default.initialized) {
41
+ _modelStore.default.houseStore.setDoorsVisibility(true);
42
+
43
+ _modelStore.default.houseStore.setFullBuildingVisibility(true);
44
+
45
+ _modelStore.default.houseStore.setCurrentWallsMaterialType('texture');
46
+
47
+ return;
48
+ }
49
+
50
+ _modelStore.default.init(json);
51
+ }, [json]);
52
+ (0, _react.useEffect)(() => {
53
+ const joystick = _nipplejs.default.create({
54
+ zone: document.querySelector('.widget-tab__model-joystick'),
55
+ color: '#F4C833',
56
+ mode: 'static',
57
+ position: {
58
+ left: '50%',
59
+ top: '50%'
60
+ }
61
+ });
62
+
63
+ joystick.on('start', () => _modelStore.default.setJoystickState(true));
64
+ joystick.on('end', () => _modelStore.default.setJoystickState(false));
65
+ joystick.on('move', (_, _ref2) => {
66
+ let {
67
+ angle
68
+ } = _ref2;
69
+ const directions = (0, _modelHelpers.getDirectionsFromDegrees)(angle.degree);
70
+
71
+ _modelStore.default.setJoystickDirections(directions);
72
+ });
73
+ }, []);
74
+
75
+ const getNextWallsMaterialType = () => {
76
+ if (houseStore.wallsMaterialType === 'texture') return 'color';
77
+ return 'texture';
78
+ };
79
+
80
+ const onImageUploaded = _ref3 => {
81
+ let {
82
+ target
83
+ } = _ref3;
84
+ if (!target.files.length) return;
85
+ const reader = new FileReader();
86
+
87
+ reader.onload = e => houseStore.addWallTexture(e.target.result);
88
+
89
+ reader.readAsDataURL(target.files[0]);
90
+ };
91
+
107
92
  return /*#__PURE__*/_react.default.createElement("div", {
108
93
  className: "widget-tab__model"
109
94
  }, /*#__PURE__*/_react.default.createElement("div", {
110
95
  className: "widget-tab__model-scene"
111
- }));
112
- };
113
-
96
+ }), /*#__PURE__*/_react.default.createElement("div", {
97
+ className: "widget-tab__model-joystick \n ".concat(_modelStore.default.currentControlsType === 'wasd' ? 'widget-tab__model-joystick--active' : '')
98
+ }), /*#__PURE__*/_react.default.createElement("div", {
99
+ className: "widget-tab-menu"
100
+ }, /*#__PURE__*/_react.default.createElement("ul", null, /*#__PURE__*/_react.default.createElement("li", {
101
+ onClick: () => setMenuState(!menuState)
102
+ }, "Menu"), menuState && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("li", {
103
+ onClick: () => _modelStore.default.setCurrentControlsType('wasd')
104
+ }, "WASD"), /*#__PURE__*/_react.default.createElement("li", {
105
+ onClick: () => _modelStore.default.setCurrentControlsType('plan')
106
+ }, "View from above"), /*#__PURE__*/_react.default.createElement("li", {
107
+ onClick: () => _modelStore.default.setCurrentControlsType('orbit')
108
+ }, "Free camera"), /*#__PURE__*/_react.default.createElement("li", {
109
+ onClick: () => houseStore.setPlanMode()
110
+ }, "Plan"), /*#__PURE__*/_react.default.createElement("li", {
111
+ onClick: () => houseStore.setFullBuildingVisibility(!houseStore.isFullBuildingVisible)
112
+ }, houseStore.isFullBuildingVisible ? 'Hide walls' : 'Show walls'), /*#__PURE__*/_react.default.createElement("li", {
113
+ onClick: () => houseStore.setDoorsVisibility(!houseStore.isDoorsVisible)
114
+ }, houseStore.isDoorsVisible ? 'Hide doors' : 'Show doors'), /*#__PURE__*/_react.default.createElement("li", {
115
+ onClick: () => houseStore.setCurrentWallsMaterialType(getNextWallsMaterialType())
116
+ }, "Material: ", houseStore.wallsMaterialType === 'texture' ? 'Texture' : 'Color'), /*#__PURE__*/_react.default.createElement("li", null, /*#__PURE__*/_react.default.createElement("label", null, "Wall color:", /*#__PURE__*/_react.default.createElement("input", {
117
+ type: "color",
118
+ onChange: _ref4 => {
119
+ let {
120
+ target
121
+ } = _ref4;
122
+ return houseStore.setCurrentWallColor(target.value);
123
+ },
124
+ style: {
125
+ background: houseStore.wallsColor
126
+ },
127
+ value: houseStore.wallsColor
128
+ }))), /*#__PURE__*/_react.default.createElement("li", null, "Wall texture:", /*#__PURE__*/_react.default.createElement("div", {
129
+ className: "widget-tab-menu__wallpapers"
130
+ }, houseStore && houseStore.wallsTextures.map((_ref5, index) => {
131
+ let {
132
+ image,
133
+ texture
134
+ } = _ref5;
135
+ return /*#__PURE__*/_react.default.createElement("img", {
136
+ key: index,
137
+ src: image,
138
+ onClick: () => houseStore.setCurrentWallTexture(texture),
139
+ alt: "texture=".concat(index)
140
+ });
141
+ }))), /*#__PURE__*/_react.default.createElement("li", null, /*#__PURE__*/_react.default.createElement("label", null, "Upload wall texture", /*#__PURE__*/_react.default.createElement("input", {
142
+ onChange: onImageUploaded,
143
+ type: "file",
144
+ accept: ".jpg, .jpeg, .png"
145
+ })))))));
146
+ });
114
147
  var _default = ModelTab;
115
148
  exports.default = _default;
@@ -35,40 +35,49 @@ const {
35
35
  } = PANOLENS.CONTROLS;
36
36
  const pathName = 'Panorama_0_0_';
37
37
 
38
+ const createPanorama = (image, index, setLoadingState) => {
39
+ const panorama = new PANOLENS.ImagePanorama(image);
40
+ panorama['panorama_id'] = index + 1;
41
+ panorama.addEventListener('progress', event => {
42
+ setLoadingState(true);
43
+
44
+ if (event.progress.loaded / event.progress.total * 100 === 100) {
45
+ setLoadingState(false);
46
+ }
47
+ });
48
+ panorama.addEventListener('enter', () => setLoadingState(false));
49
+ return panorama;
50
+ };
51
+
38
52
  const getPanoramas = (json, images, setLoadingState) => {
53
+ if (!json) return images.map((image, index) => createPanorama(image, index, setLoadingState));
39
54
  return json.Floors[0].Units[0].Rooms.reduce((acc, jsonRoom, index) => {
40
55
  const image = images.find(img => img.includes(pathName + index));
41
56
  if (!image) return acc;
42
- const panorama = new PANOLENS.ImagePanorama(image);
43
- panorama['panorama_id'] = index + 1;
57
+ const panorama = createPanorama(image, index, setLoadingState);
44
58
  panorama['room_id'] = jsonRoom.ID;
45
- panorama.addEventListener('progress', event => {
46
- setLoadingState(true);
47
-
48
- if (event.progress.loaded / event.progress.total * 100 === 100) {
49
- setLoadingState(false);
50
- }
51
- });
52
- panorama.addEventListener('enter', () => setLoadingState(false));
53
59
  acc.push(panorama);
54
60
  return acc;
55
61
  }, []);
56
62
  };
57
63
 
58
64
  const getPanoramaRooms = (json, panoramas) => {
59
- const {
60
- Vertices,
61
- Floors
62
- } = json;
63
- const {
64
- Walls
65
- } = Floors[0];
66
65
  return panoramas.map((panorama, index) => {
67
- const currentRoom = Floors[0].Units[0].Rooms.find(room => room.ID === panorama['room_id']);
66
+ let currentRoom = {
67
+ Type: "Room - ".concat(panorama['panorama_id'])
68
+ };
69
+
70
+ if (json) {
71
+ currentRoom = json.Floors[0].Units[0].Rooms.find(room => room.ID === panorama['room_id']);
72
+ }
73
+
68
74
  const {
69
75
  left,
70
76
  top
71
- } = (0, _panoramaHelpers.findRoomCenter)(currentRoom, Walls, Vertices);
77
+ } = json ? (0, _panoramaHelpers.findRoomCenter)(currentRoom, json.Floors[0].Walls, json.Vertices) : {
78
+ left: 0,
79
+ top: 0
80
+ };
72
81
  return {
73
82
  type: currentRoom.Type,
74
83
  id: index,
@@ -121,6 +130,7 @@ const PanoramaTab = _ref => {
121
130
  X: 1,
122
131
  Y: 1
123
132
  });
133
+ const isMapDisabled = !json;
124
134
 
125
135
  const changePanorama = (panorama, index) => {
126
136
  setCurrentRoomIndex(index);
@@ -181,20 +191,20 @@ const PanoramaTab = _ref => {
181
191
  }), loadingState && /*#__PURE__*/_react.default.createElement(_Loader.default, {
182
192
  absolute: true
183
193
  }), /*#__PURE__*/_react.default.createElement("div", {
184
- className: "widget-tab__panorama-menu"
194
+ className: "widget-tab-menu"
185
195
  }, /*#__PURE__*/_react.default.createElement("ul", null, /*#__PURE__*/_react.default.createElement("li", {
186
196
  onClick: () => setMenuState(!menuState)
187
197
  }, "Rooms"), menuState && panoramaRooms.map((room, index) => /*#__PURE__*/_react.default.createElement("li", {
188
198
  key: index,
189
199
  onClick: () => changePanorama(room.panorama, index)
190
200
  }, currentRoomIndex === index && '• ', " ", room.type)))), /*#__PURE__*/_react.default.createElement("div", {
191
- className: "widget-tab__panorama-map"
201
+ className: "widget-tab__panorama-map ".concat(planImage ? '' : 'widget-tab__panorama-map--hidden')
192
202
  }, /*#__PURE__*/_react.default.createElement("img", {
193
203
  src: planImage,
194
204
  className: isMapActive ? 'active' : '',
195
205
  onClick: toggleMap,
196
206
  alt: "plan"
197
- }), panoramaRooms.map((room, index) => /*#__PURE__*/_react.default.createElement("div", {
207
+ }), !isMapDisabled && panoramaRooms.map((room, index) => /*#__PURE__*/_react.default.createElement("div", {
198
208
  key: index,
199
209
  style: {
200
210
  left: "".concat(room.left * planScale.X, "px"),