c80_map_floors 0.1.0.1

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 (92) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.travis.yml +3 -0
  4. data/CODE_OF_CONDUCT.md +13 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +67 -0
  8. data/Rakefile +1 -0
  9. data/app/admin/c80_map_floors/floors.rb +57 -0
  10. data/app/admin/c80_map_floors/map_buildings.rb +49 -0
  11. data/app/admin/c80_map_floors/settings.rb +32 -0
  12. data/app/assets/javascripts/buttons/admin_buttons/button_area_link.js +91 -0
  13. data/app/assets/javascripts/buttons/admin_buttons/button_building_link.js +91 -0
  14. data/app/assets/javascripts/buttons/admin_buttons/button_cancel_create.js +21 -0
  15. data/app/assets/javascripts/buttons/admin_buttons/button_cancel_remove.js +23 -0
  16. data/app/assets/javascripts/buttons/admin_buttons/button_complete_create.js +22 -0
  17. data/app/assets/javascripts/buttons/admin_buttons/button_edit.js +96 -0
  18. data/app/assets/javascripts/buttons/admin_buttons/button_new.js +46 -0
  19. data/app/assets/javascripts/buttons/admin_buttons/button_remove.js +23 -0
  20. data/app/assets/javascripts/buttons/admin_buttons/button_save.js +111 -0
  21. data/app/assets/javascripts/buttons/button_back_to_map.js +84 -0
  22. data/app/assets/javascripts/buttons/zoom_buttons.js +78 -0
  23. data/app/assets/javascripts/c80_map_floors.js.coffee +23 -0
  24. data/app/assets/javascripts/events/app_event.js +15 -0
  25. data/app/assets/javascripts/map_objects/area.js +251 -0
  26. data/app/assets/javascripts/map_objects/building.js +294 -0
  27. data/app/assets/javascripts/map_objects/dot.js +14 -0
  28. data/app/assets/javascripts/map_objects/floor.js +10 -0
  29. data/app/assets/javascripts/src/main.js +1421 -0
  30. data/app/assets/javascripts/src/state_controller.js +322 -0
  31. data/app/assets/javascripts/src/utils/map_utils.js +23 -0
  32. data/app/assets/javascripts/src/utils/opacity_buttons_utils.js +15 -0
  33. data/app/assets/javascripts/src/utils/utils.js +140 -0
  34. data/app/assets/javascripts/svg_elements/area_label.js +25 -0
  35. data/app/assets/javascripts/svg_elements/building_label.js +65 -0
  36. data/app/assets/javascripts/svg_elements/helper.js +36 -0
  37. data/app/assets/javascripts/svg_elements/polygon.js +194 -0
  38. data/app/assets/javascripts/view/save_preloader.js +30 -0
  39. data/app/assets/stylesheets/c80_map_floors.scss +4 -0
  40. data/app/assets/stylesheets/map.scss +1464 -0
  41. data/app/assets/stylesheets/view/buttons/area_order_button.scss +16 -0
  42. data/app/assets/stylesheets/view/buttons/back_to_map_button.scss +28 -0
  43. data/app/assets/stylesheets/view/elems/building_info.scss +54 -0
  44. data/app/assets/stylesheets/view/elems/free_areas_label.scss +116 -0
  45. data/app/assets/stylesheets/view/elems/map_objects/map_object_image_bg.scss +10 -0
  46. data/app/assets/stylesheets/view/modal_window.scss +13 -0
  47. data/app/assets/stylesheets/view/save_preloader.scss +206 -0
  48. data/app/controllers/c80_map_floors/ajax_controller.rb +65 -0
  49. data/app/controllers/c80_map_floors/application_controller.rb +6 -0
  50. data/app/controllers/c80_map_floors/map_ajax_controller.rb +70 -0
  51. data/app/helpers/c80_map_floors/application_helper.rb +28 -0
  52. data/app/models/c80_map_floors/area.rb +20 -0
  53. data/app/models/c80_map_floors/area_representator.rb +75 -0
  54. data/app/models/c80_map_floors/base_map_object.rb +41 -0
  55. data/app/models/c80_map_floors/building_representator.rb +72 -0
  56. data/app/models/c80_map_floors/floor.rb +37 -0
  57. data/app/models/c80_map_floors/map_building.rb +45 -0
  58. data/app/models/c80_map_floors/map_json.rb +35 -0
  59. data/app/models/c80_map_floors/setting.rb +32 -0
  60. data/app/uploaders/c80_map_floors/building_image_uploader.rb +31 -0
  61. data/app/uploaders/c80_map_floors/floor_image_uploader.rb +33 -0
  62. data/app/uploaders/c80_map_floors/map_image_uploader.rb +31 -0
  63. data/app/views/c80_map_floors/_map_row_index.html.erb +40 -0
  64. data/app/views/c80_map_floors/ajax/fetch_unlinked_areas.js.erb +7 -0
  65. data/app/views/c80_map_floors/ajax/fetch_unlinked_buildings.js.erb +7 -0
  66. data/app/views/c80_map_floors/ajax/map_edit_buttons.js.erb +36 -0
  67. data/app/views/c80_map_floors/ajax/shared/_map_creating.html.erb +6 -0
  68. data/app/views/c80_map_floors/ajax/shared/_map_editing.html.erb +4 -0
  69. data/app/views/c80_map_floors/ajax/shared/_map_removing.html.erb +5 -0
  70. data/app/views/c80_map_floors/ajax/shared/_select_list_unlinked_areas.html.erb +6 -0
  71. data/app/views/c80_map_floors/ajax/shared/_select_list_unlinked_buildings.html.erb +10 -0
  72. data/app/views/c80_map_floors/shared/_modal_window.html.erb +28 -0
  73. data/app/views/c80_map_floors/shared/_save_preloader.html.erb +3 -0
  74. data/app/views/c80_map_floors/shared/map_row/_area_order_button.html.erb +7 -0
  75. data/app/views/c80_map_floors/shared/map_row/_building_info.html.erb +17 -0
  76. data/bin/console +14 -0
  77. data/bin/setup +7 -0
  78. data/c80_map_floors.gemspec +28 -0
  79. data/config/routes.rb +4 -0
  80. data/db/migrate/20161015190000_create_c80_map_floors_settings.rb +8 -0
  81. data/db/migrate/20161015190001_create_c80_map_floors_map_buildings.rb +10 -0
  82. data/db/migrate/20161015190002_create_c80_map_floors_areas.rb +12 -0
  83. data/db/migrate/20161015190003_add_building_representator_to_c80_map_floors_buildings.rb +6 -0
  84. data/db/migrate/20161015190004_create_c80_map_floors_floors.rb +16 -0
  85. data/db/migrate/20161019111010_add_title_to_c80_map_floors_buildings.rb +5 -0
  86. data/db/migrate/20161020184040_add_coords_img_to_c80_map_floors_buildings.rb +5 -0
  87. data/db/seeds/c80_map_floors_01_fill_map_settings.rb +6 -0
  88. data/db/seeds/c80_map_floors_02_create_test_area.rb +7 -0
  89. data/lib/c80_map_floors.rb +8 -0
  90. data/lib/c80_map_floors/engine.rb +23 -0
  91. data/lib/c80_map_floors/version.rb +3 -0
  92. metadata +218 -0
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+
3
+ function CancelCreatingButton() {
4
+
5
+ var _map = null;
6
+ var _this = this;
7
+ _this.el = null;
8
+
9
+ this.onClick = function (e) {
10
+ console.log("<CancelCreatingButton.onClick>");
11
+ e.preventDefault();
12
+ _map.setMode("editing");
13
+ };
14
+
15
+ this.init = function (button_css_selector, link_to_map) {
16
+ _map = link_to_map;
17
+ _this.el = $(button_css_selector);
18
+ _this.el.on('click', this.onClick);
19
+ };
20
+
21
+ }
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+
3
+ function CancelRemoveButton() {
4
+
5
+ var _map = null;
6
+ var _this = this;
7
+ _this.el = null;
8
+
9
+ _this.onClick = function (e) {
10
+ if (_this.el.hasClass('disabled')) return;
11
+ e.preventDefault();
12
+
13
+ console.log("<CancelRemoveButton.onClick> Выходим из режима удаления полигона.");
14
+ _map.setMode('editing');
15
+
16
+ };
17
+
18
+ _this.init = function (button_css_selector, link_to_map) {
19
+ _map = link_to_map;
20
+ _this.el = $(button_css_selector);
21
+ _this.el.on('click', _this.onClick);
22
+ };
23
+ }
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+
3
+ function CompleteCreatingButton() {
4
+
5
+ var _map = null;
6
+ var _this = this;
7
+ _this.el = null;
8
+
9
+ _this.onClick = function (e) {
10
+ console.log("<CompleteCreatingButton.onClick>");
11
+ if (e != null) e.preventDefault();
12
+ _map.onDrawStop();
13
+ };
14
+
15
+ _this.init = function (button_css_selector, link_to_map) {
16
+ _map = link_to_map;
17
+ _this.el = $(button_css_selector);
18
+ _this.el.on('click', _this.onClick);
19
+ _map.complete_creating_button_klass = _this;
20
+ };
21
+
22
+ }
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+
3
+ // именно эта кнопка контролирует переходы между состояниями:
4
+ // - viewing, editing;
5
+ // - view_building, edit_building;
6
+ // - view_area, edit_area;
7
+ function EditButton() {
8
+
9
+ var _map = null;
10
+ var _this = this;
11
+ _this.state = 'init'; // editing / viewing
12
+ _this.el = null;
13
+
14
+ // состояние этой кнопки извне меняет приложение,
15
+ // когда входим в здание\площадь (вот тут [a1x7]),
16
+ // и чтобы не происходило бесконечного зацикленного вызова,
17
+ // вводится флаг mark_change_only_inner_state
18
+ this.setState = function (state,mark_change_only_inner_state) {
19
+ if (mark_change_only_inner_state == undefined) {
20
+ mark_change_only_inner_state = false;
21
+ }
22
+ console.log("<EditButton.setState> state = " + state);
23
+
24
+ // этот код коррелирует с [x9cs7]
25
+ _this.state = state;
26
+ _this.el.removeClass('editing');
27
+ _this.el.removeClass('viewing');
28
+ _this.el.removeClass('removing');
29
+ _this.el.removeClass('view_building');
30
+ _this.el.removeClass('edit_building');
31
+ _this.el.removeClass('view_area');
32
+ _this.el.removeClass('edit_area');
33
+ _this.el.addClass(state);
34
+
35
+ if (!mark_change_only_inner_state) {
36
+ _map.setMode(state);
37
+ }
38
+
39
+ };
40
+
41
+ this.onClick = function (e) {
42
+ e.preventDefault();
43
+
44
+ // если после исполнения switch..case эта перменная будет true - значит надо будет вызвать кое-какой код
45
+ var mark_restore_svg_overlay = false;
46
+
47
+ switch (_this.state) {
48
+ case 'editing':
49
+ _this.setState('viewing');
50
+ break;
51
+
52
+ case 'viewing':
53
+ _this.setState('editing');
54
+ break;
55
+
56
+ case 'view_building':
57
+ _this.setState('edit_building');
58
+ break;
59
+
60
+ // находились в режиме редактирования здания, и перешли в режим просмотра здания
61
+ case 'edit_building':
62
+ _this.setState('view_building');
63
+ mark_restore_svg_overlay = true;
64
+ break;
65
+
66
+ case 'view_area':
67
+ _this.setState('edit_area');
68
+ // спрячем от клика мышки все полигоны из svg_overlay, кроме редактируемого полигона
69
+ MapUtils.svgOverlayHideAllExcept(_map.last_clicked_g);
70
+ break;
71
+
72
+ // находились в режиме редактирования площади, и перешли в режим просмотра площади
73
+ case 'edit_area':
74
+ _this.setState('view_area');
75
+ mark_restore_svg_overlay = true;
76
+ break;
77
+
78
+ }
79
+
80
+ // покажем для клика мышкой все полигоны из svg_overlay
81
+ if (mark_restore_svg_overlay) {
82
+ MapUtils.svgOverlayRestore(_map.last_clicked_g);
83
+ _map.last_clicked_g = null;
84
+ }
85
+
86
+ };
87
+
88
+ this.init = function (button_css_selector, link_to_map) {
89
+ _map = link_to_map;
90
+ _this.el = $(button_css_selector);
91
+ _this.state = _map.mode;
92
+ _this.el.addClass(_map.mode);
93
+ _this.el.on('click', this.onClick);
94
+ };
95
+
96
+ }
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+
3
+ function NewButton() {
4
+
5
+ var _map = null;
6
+ var _this = this;
7
+ _this.state = 'init'; // creating / editing
8
+ _this.el = null;
9
+
10
+ _this.setState = function (state) {
11
+
12
+ _this.state = state;
13
+ _this.el.removeClass('creating');
14
+ _this.el.removeClass('editing');
15
+ _this.el.addClass(state);
16
+
17
+ _map.setMode(state);
18
+
19
+ };
20
+
21
+ _this.resetState = function () {
22
+ _this.state = 'editing';
23
+ _this.el.removeClass('creating');
24
+ _this.el.removeClass('editing');
25
+ _this.el.addClass('editing');
26
+ };
27
+
28
+ _this.onClick = function (e) {
29
+ if (_this.el.hasClass('disabled')) return;
30
+ e.preventDefault();
31
+
32
+ if (_this.state == 'creating') {
33
+ _this.setState('editing');
34
+ } else {
35
+ console.log("<NewButton.onClick> Переходим в режим создания полигона.");
36
+ _this.setState('creating');
37
+ }
38
+ };
39
+
40
+ _this.init = function (button_css_selector, link_to_map) {
41
+ _map = link_to_map;
42
+ _this.el = $(button_css_selector);
43
+ _this.setState(_map.mode);
44
+ _this.el.on('click', _this.onClick);
45
+ };
46
+ }
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+
3
+ function RemoveButton() {
4
+
5
+ var _map = null;
6
+ var _this = this;
7
+ _this.el = null;
8
+
9
+ _this.onClick = function (e) {
10
+ if (_this.el.hasClass('disabled')) return;
11
+ e.preventDefault();
12
+
13
+ console.log("<RemoveButton.onClick> Переходим в режим удаления полигона.");
14
+ _map.setMode('removing');
15
+
16
+ };
17
+
18
+ _this.init = function (button_css_selector, link_to_map) {
19
+ _map = link_to_map;
20
+ _this.el = $(button_css_selector);
21
+ _this.el.on('click', _this.onClick);
22
+ };
23
+ }
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+
3
+ function SaveChangesButton() {
4
+
5
+ var _map = null;
6
+ var _this = this;
7
+ _this.el = null;
8
+
9
+ var sendDataToServer = function () {
10
+
11
+ var areas;
12
+ var buildings;
13
+ var i, len;
14
+
15
+ len = _map.drawn_areas.length;
16
+ if (len > 0) {
17
+ areas = [];
18
+ for (i = 0; i < len; i++) {
19
+ areas.push(_map.drawn_areas[i].to_json());
20
+ }
21
+ }
22
+
23
+ len = _map.drawn_buildings.length;
24
+ if (len > 0) {
25
+ buildings = [];
26
+ for (i = 0; i < len; i++) {
27
+ buildings.push(_map.drawn_buildings[i].to_json());
28
+ }
29
+ }
30
+
31
+ $.ajax({
32
+ url: '/save_map_data',
33
+ type: 'POST',
34
+ data: {
35
+ areas: areas,
36
+ buildings: buildings
37
+ },
38
+ dataType: 'json'
39
+ }).done(sendDataToServerDone);
40
+ };
41
+
42
+ var sendDataToServerDone = function (data, result) {
43
+
44
+ //console.log("<ButtonSave.sendDataToServerDone> data,result:");
45
+ //console.log(data);
46
+ // => Object
47
+ // areas: Array[1]
48
+ // 0: Object:
49
+ // id: 16,
50
+ // old_temp_id: "76400",
51
+ // buildings: Array,
52
+ // updated_locations_json: null
53
+ //console.log(result);
54
+ // => success
55
+
56
+ _map.save_preloader_klass.hide();
57
+
58
+ _map.data = data["updated_locations_json"];
59
+
60
+ //var i;
61
+ //var iarea_resp_params;
62
+ //var idrawn_area;
63
+ //for (i = 0; i< data["areas"].length; i++) {
64
+ // iarea_resp_params = data["areas"][i];
65
+ // найдем в массиве drawn_areas область, данные о которой сохранили на сервере
66
+ //idrawn_area = utils.getById(iarea["old_temp_id"], _map.drawn_areas);
67
+ //idrawn_area["id"] = iarea["id"];
68
+ //
69
+ //}
70
+
71
+ _map.drawn_areas = [];
72
+ _map.drawn_buildings = [];
73
+ _this.check_and_enable();
74
+
75
+ };
76
+
77
+ _this.onClick = function (e) {
78
+ if (_this.el.hasClass('disabled')) return;
79
+ e.preventDefault();
80
+ _map.save_preloader_klass.show();
81
+ sendDataToServer();
82
+ };
83
+
84
+ _this.init = function (button_css_selector, link_to_map) {
85
+ _map = link_to_map;
86
+ _this.el = $(button_css_selector);
87
+ _this.el.on('click', _this.onClick);
88
+ };
89
+
90
+ _this.check_and_enable = function () {
91
+
92
+ //check
93
+ var mark_dirty = _map.drawn_areas.length || _map.drawn_buildings.length;
94
+
95
+ // enable
96
+ if (mark_dirty) {
97
+ _this.el.removeClass('mapplic-disabled');
98
+ } else {
99
+ _this.el.addClass('mapplic-disabled');
100
+ }
101
+
102
+ };
103
+
104
+ _this.hide = function () {
105
+ _this.el.css('display','none');
106
+ };
107
+
108
+ _this.show = function () {
109
+ _this.el.css('display','block');
110
+ };
111
+ }
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+
3
+ function BackToMapButton() {
4
+
5
+ var _map = null;
6
+ var _this = this;
7
+
8
+ var _cnt = null;
9
+ var _btn = null;
10
+
11
+ var _$building_info = null;
12
+
13
+ var _onClick = function () {
14
+ _map.setMode('viewing');
15
+
16
+ if (_map.current_building) {
17
+ _map.current_building.exit();
18
+ _map.current_building = null;
19
+ }
20
+
21
+ if (_map.current_area) {
22
+ _map.current_area.exit();
23
+ _map.current_area = null;
24
+ }
25
+
26
+ _map.svgRemoveAllNodes();
27
+ _map.draw_childs(_map.data["buildings"]);
28
+
29
+ if (_map.initial_map_position != null) {
30
+ /* TODO:: необходимо удостовериться, что параметр scale используется и используется правильно*/
31
+ _map.moveTo(
32
+ _map.initial_map_position.x,
33
+ _map.initial_map_position.y,
34
+ _map.initial_map_position.scale,
35
+ 400,
36
+ 'easeInOutCubic'
37
+ );
38
+ }
39
+
40
+ };
41
+
42
+ _this.init = function (parent_div_selector, link_to_map) {
43
+ _map = link_to_map;
44
+ _cnt = $('<div></div>').addClass('back_to_map_button');
45
+ _cnt.appendTo($(parent_div_selector));
46
+ _btn = $('<a href="#" id="BackToMapButton">Обратно на карту</a>');
47
+ _btn.on('click', _onClick);
48
+ _cnt.append(_btn);
49
+
50
+ _$building_info = $('.building_info');
51
+
52
+ };
53
+
54
+ _this.show = function () {
55
+
56
+ // хардкод - подгоняем под длину анимации, прописанной в css
57
+ setTimeout(__show, 800);
58
+
59
+
60
+ };
61
+ var __show = function () {
62
+ // фиксируем
63
+ var building_info_top = _$building_info.offset().top;
64
+ var building_info_height = _$building_info.height();
65
+
66
+ // считаем
67
+ var btn_top = building_info_top + building_info_height;
68
+ var btn_left = _$building_info.offset().left;
69
+
70
+ // позиционируем
71
+ _btn.css('top', btn_top + 'px');
72
+ _btn.css('left', btn_left + 'px');
73
+
74
+ // показываем
75
+ _btn.css('opacity','1');
76
+ _cnt.css('display', 'block');
77
+ };
78
+
79
+ _this.hide = function () {
80
+ _cnt.css('display', 'none');
81
+ _btn.css('opacity', '0');
82
+ }
83
+
84
+ }
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+
3
+ // Zoom Buttons
4
+ function ZoomButtons() {
5
+
6
+ var self = this;
7
+ var _map = null;
8
+ this.el = null;
9
+
10
+ this.init = function (options, link_to_map) {
11
+ var mt = options["height"] - 10;
12
+ _map = link_to_map;
13
+
14
+ //var div_container = $('<div></div>')
15
+ // .addClass("container")
16
+ // .attr("id",'container_buttons')
17
+ // .appendTo(_map.container)
18
+ // .css('margin-top',mt+"px");
19
+ var div_container = $("#container_buttons");
20
+ div_container.css('margin-top', mt + "px");
21
+
22
+ //this.el = $('<div></div>').addClass('mzoom_buttons').appendTo(div_container);
23
+ this.el = $('.mzoom_buttons');
24
+
25
+ this.zoomin = $('<a></a>').attr('href', '#').addClass('mapplic-zoomin-button').appendTo(this.el);
26
+
27
+ this.zoomin.on('click touchstart', function (e) {
28
+ e.preventDefault();
29
+
30
+ var scale = _map.normalizeScale(_map.scale + 0.2);
31
+ //_map.scale = _map.normalizeScale(scale + .2);
32
+
33
+ //_map.x = _map.normalizeX(_map.x - (_map.container.width() / 2 - _map.x) * (_map.scale / scale - 1));
34
+ //_map.y = _map.normalizeY(_map.y - (_map.container.height() / 2 - _map.y) * (_map.scale / scale - 1));
35
+
36
+ self.__execute_zoom(scale);
37
+
38
+ });
39
+
40
+ this.zoomout = $('<a></a>').attr('href', '#').addClass('mapplic-zoomout-button').appendTo(this.el);
41
+
42
+ this.zoomout.on('click touchstart', function (e) {
43
+ e.preventDefault();
44
+
45
+ var scale = _map.normalizeScale(_map.scale - .2);
46
+ //_map.scale = _map.normalizeScale(scale - .2);
47
+
48
+ //_map.x = _map.normalizeX(_map.x - (_map.container.width() / 2 - _map.x) * (_map.scale / scale - 1));
49
+ //_map.y = _map.normalizeY(_map.y - (_map.container.height() / 2 - _map.y) * (_map.scale / scale - 1));
50
+
51
+ self.__execute_zoom(scale);
52
+
53
+ });
54
+ };
55
+
56
+ self.__execute_zoom = function (scale) {
57
+ var x = _map.normalizeX({
58
+ x: _map.x - (_map.container.width() / 2 - _map.x) * (scale / _map.scale - 1),
59
+ scale: scale
60
+ });
61
+
62
+ var y = _map.normalizeY({
63
+ y: _map.y - (_map.container.width() / 2 - _map.y) * (scale / _map.scale - 1),
64
+ scale: scale
65
+ });
66
+
67
+ _map.moveTo(x, y, scale, 400, 'easeInOutCubic');
68
+ _map.mark_virgin = false;
69
+ };
70
+
71
+ this.update = function (scale) {
72
+ this.zoomin.removeClass('mapplic-disabled');
73
+ this.zoomout.removeClass('mapplic-disabled');
74
+ if (scale == _map.o.fitscale) this.zoomout.addClass('mapplic-disabled');
75
+ else if (scale == _map.o.maxscale) this.zoomin.addClass('mapplic-disabled');
76
+ };
77
+
78
+ }