c80_push 0.1.0.1 → 0.1.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bc71bf6b52804cacd8264f3b6c11f871a0a98941
4
- data.tar.gz: fda41529b939dfb82b720d781a5e809fd346a96b
3
+ metadata.gz: b4d991e9e1a4d40ab4a2788f801fc5bda42e61d2
4
+ data.tar.gz: 37d7c1a99822e278f8b2b4db16255fdd29a187a8
5
5
  SHA512:
6
- metadata.gz: 1aaf65ac0642e9df24e8b7741e6f8a0f33d1d0d5c2c1ab7e9039f2af2ee132aeb546989ca1e20c6480d9323dfa171d02f7d0e260193e50b361dce565fe9adae5
7
- data.tar.gz: d968c22cf4ee2de729b71fa4caf2befb8685e2b536578dfb3bdd16aa18ff4d11446398caa769f1882423a07f83ef3ce494e68f885ba7bdbe64ed57cce9a2fae7
6
+ metadata.gz: c88589031569da99e0158285b792473c6b0c1a580106b6830ad1ffaee861546c219a760983054d5d126da6acf185fb4bdfb8060ad8c2a6eceb171381de09d5f1
7
+ data.tar.gz: 9a7b1e94d5105aed752b535222df57341519ae0e7fde738650edda28ccc362185b010eea44616551fbc6b039440b050f3d2bffdb2a59b05609be3d9bd67f595c
data/README.md CHANGED
@@ -56,15 +56,49 @@ Add these lines to host app's `active_admin.js.coffee`:
56
56
  Add these lines to host app's 'application.js.coffee':
57
57
 
58
58
  ```js
59
+ #= require bootstrap
60
+ #= require bootstrap-select
59
61
  #= require c80_push
60
62
  ```
61
63
 
62
64
  Add these lines to host app's 'application.scss':
63
65
 
64
66
  ```css
67
+ @import "bootstrap-sprockets";
68
+ @import "bootstrap";
69
+ @import "bootstrap-select";
65
70
  @include "c80_push";
66
71
  ```
67
72
 
73
+ ## Процесс разработки JS функционала
74
+
75
+ Теперь пора заняться js.
76
+
77
+ * [X] Прикрутить `selectpicker`: выводить туда только те регионы, в которых есть дилеры,
78
+ у которых есть офисы.
79
+
80
+ * [X] Вставить заголовок "Выберите Регион".
81
+
82
+ * [X] При первом входе на карту: должны отражаться все офисы.
83
+
84
+ - [X] Должен рассчитываться `bounding rectangle` и все точки должны быть видны
85
+ на рабочей области (никто не должен выходить за рамки)
86
+
87
+ * [ ] При наведении/клике на точку на карте:
88
+
89
+ - [X] должен появляться хинт с деталями офиса
90
+ - [ ] слева должен подсвечиваться соответствующий `.li_office`.
91
+
92
+ * [X] При наведении/клике на `.li_office` - должна подсвечиваться соответствующая
93
+ точка на карте.
94
+
95
+ * [ ] Вставить из `psd` синий маркер.
96
+
97
+ * [X] Когда меняется регион:
98
+
99
+ * [X] Должны отобразиться релевантные `.li_office`
100
+ * [X] Должны отобразиться релевантные точки на карте.
101
+
68
102
  ## Цитата из ТЗ
69
103
 
70
104
  > Данный раздел представляет собой список компаний, у которых указаны
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Сфокусироваться на точке на карте.
3
+ * Если надо - открыть balloon.
4
+ * @param id : id офиса.
5
+ */
6
+ function _item_toggle(id) {
7
+ //console.log('<_item_toggle> id: ' + id);
8
+
9
+ var it = dealers_map.geoObjects.getIterator(),
10
+ group;
11
+
12
+ while(group = it.getNext()) {
13
+ //console.log(group.properties);
14
+ if (group.properties !== undefined) {
15
+ for (var i = 0, len = group.getLength(); i < len; i++) {
16
+ var placemark = group.get(i);
17
+ //console.log(placemark.properties.get('id'));
18
+ if (placemark.properties.get('id') === id) {
19
+ //console.log('+ ' + placemark.balloon.isOpen());
20
+ if (placemark.balloon.isOpen()) {
21
+ placemark.balloon.close();
22
+ }
23
+ else {
24
+ dealers_map.panTo(placemark.geometry.getCoordinates(), {
25
+ delay: 0
26
+ }).then(function () {
27
+ placemark.balloon.open();
28
+ });
29
+ }
30
+ return;
31
+ }
32
+ }
33
+ break;
34
+ }
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Начинаем слушать клики по .li_office.
40
+ * При клике - вызовется _item_toggle.
41
+ */
42
+ function _dealers_left_list_clicks() {
43
+ $('.li_office').on("click", function (e) {
44
+ e.preventDefault();
45
+ var office_id = $(this).data('id');
46
+ _item_toggle(office_id);
47
+ });
48
+ }
49
+
50
+ $(document).ready(_dealers_left_list_clicks);
@@ -0,0 +1,14 @@
1
+ /**
2
+ * В списке дилеров слева от карты оставить только тех,
3
+ * кто принадлежит указанному региону.
4
+ *
5
+ * @param region_id
6
+ */
7
+ function dealers_left_list_filter(region_id) {
8
+ if (region_id === 'all') {
9
+ $('.li_region').css('display', 'block');
10
+ } else {
11
+ $('.li_region').css('display', 'none');
12
+ $('.li_region#region_' + region_id).css('display','block');
13
+ }
14
+ }
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+
3
+ var dealers_map;
4
+
5
+ $(document).ready(function() {
6
+
7
+ if ($('#dealers_map_container').length) {
8
+ //noinspection JSUnresolvedVariable
9
+ ymaps.ready(function() {
10
+
11
+ //noinspection JSUnresolvedVariable,JSUnresolvedFunction
12
+ dealers_map = new ymaps.Map('dealers_map_container', {
13
+ center: [55, 37],
14
+ zoom: 10,
15
+ controls: ['zoomControl']
16
+ });
17
+
18
+ map_set_objects('all');
19
+
20
+ });
21
+ }
22
+
23
+ });
@@ -0,0 +1,26 @@
1
+ // нарисовать на карте объекты из указанного
2
+ // хэша offices[region_id]
3
+
4
+ function map_set_objects(region_id) {
5
+
6
+ var arr = offices[region_id];
7
+ // console.log(arr);
8
+ var n = arr['count'];
9
+
10
+ // соберём коллекцию точек
11
+ var c = new ymaps.GeoObjectCollection();
12
+ var icoords, iprops; // loop vars
13
+ for (var i = 0; i < n; i++) {
14
+ icoords = arr['coords'][i];
15
+ iprops = arr['props'][i];
16
+ c.add(new ymaps.Placemark(icoords, iprops));
17
+ }
18
+
19
+ // сначала уберём все точки
20
+ dealers_map.geoObjects.each(function(o) {
21
+ dealers_map.geoObjects.remove(o)
22
+ });
23
+
24
+ dealers_map.geoObjects.add(c);
25
+ dealers_map.setBounds(c.getBounds());
26
+ }
@@ -0,0 +1,20 @@
1
+ var $select_region;
2
+
3
+ /**
4
+ * Когда меняется регион:
5
+ * - Должны отобразиться релевантные `.li_office`
6
+ * - Должны отобразиться релевантные точки на карте.
7
+ */
8
+ var _select_region_on_change = function() {
9
+ var region_id = $(this).val();
10
+ // console.log('<_select_region_on_change> region_id = ' + region_id);
11
+ map_set_objects(region_id);
12
+ dealers_left_list_filter(region_id);
13
+ };
14
+
15
+ var select_region_init = function() {
16
+ //noinspection JSUnresolvedFunction
17
+ $select_region = $('#select_region').selectpicker();
18
+ $select_region.change(_select_region_on_change);
19
+ };
20
+ $(document).ready(select_region_init);
@@ -8,7 +8,12 @@ div.c80_push_page_dealers {
8
8
 
9
9
  div.select_region_row {
10
10
  height: 53px;
11
- margin-bottom: 25px;
11
+ margin-bottom: 15px;
12
+ padding: 9px;
13
+
14
+ div.select_wrapper {
15
+ float: right;
16
+ }
12
17
  }
13
18
 
14
19
  div.bottom_row {
@@ -5,9 +5,22 @@ div.c80_push_page_dealers {
5
5
 
6
6
  div.select_region_row {
7
7
  background-color: #E0001A;
8
+ div.select_wrapper {
9
+
10
+ }
8
11
  }
9
12
 
10
- div#dealers_map_container {
13
+ div.bottom_row {
14
+
15
+ > div {
16
+ }
17
+
18
+ div.dealers_list {
19
+ background-color: #f5f5f5;
20
+ }
21
+
22
+ div#dealers_map_container {
23
+ }
11
24
 
12
25
  }
13
26
 
@@ -2,6 +2,8 @@
2
2
  margin: 0;
3
3
  padding: 0;
4
4
  list-style: none;
5
+ border-top: 1px #B2B2B2 solid;
6
+ background-color: #ffffff;
5
7
 
6
8
  .li_region {
7
9
 
@@ -16,6 +18,8 @@
16
18
  padding: 0; //5px 5px 10px 15px;
17
19
  list-style: none;
18
20
  border: 1px #B2B2B2 solid;
21
+ border-bottom: none;
22
+ border-top: none;
19
23
 
20
24
  .li_dealer {
21
25
  padding: 15px;
@@ -74,6 +78,7 @@
74
78
 
75
79
  &:hover {
76
80
  border-bottom: 1px transparent solid;
81
+ z-index: 1;
77
82
  &:after {
78
83
  display: block;
79
84
  background-color: #e8e8e8;
@@ -84,6 +89,7 @@
84
89
  border-bottom: 1px transparent solid;
85
90
  color: #e4e0e0;
86
91
  position: relative;
92
+ z-index: 1;
87
93
 
88
94
  &:after {
89
95
  display: block;
@@ -6,10 +6,103 @@ module C80Push
6
6
  module ApplicationHelper
7
7
 
8
8
  def c80_push_render_page_dealers
9
+
10
+ # список регионов, включая дилеры и офисы
11
+ region_dealer_office_list = Region.includes(dealers: :offices)
12
+
13
+ # хэш для построения точек на Yandex карте
14
+ ymap_hash = prepare_ymap_hash(region_dealer_office_list)
15
+
16
+ # список регионов для select-а "Выберите регион"
17
+ r = prepare_regions_hash(region_dealer_office_list)
18
+
9
19
  render partial: 'c80_push/shared/page_dealers',
10
20
  locals: {
21
+ rdo_list: region_dealer_office_list,
22
+ regions_list: r,
23
+ ymap_hash: ymap_hash
11
24
  }
12
25
  end
13
26
 
27
+ private
28
+
29
+ # специально для яваскрипта, работающего с yandex картой,
30
+ # на основе +rdo+ собираем координаты всех офисов
31
+ # в хеше вида:
32
+ #
33
+ # {
34
+ # all: { - здесь собираем все офисы всех регионов (для лаконичности js)
35
+ # coords: [],
36
+ # props: []
37
+ # }
38
+ # <region_id>: [ - данные офисов разложены по регионам
39
+ # coords: [],
40
+ # props: []
41
+ # ]
42
+ # }
43
+ #
44
+ # noinspection RubyResolve
45
+ def prepare_ymap_hash(rdo)
46
+ res = {
47
+ all: {
48
+ coords: [],
49
+ props: []
50
+ }
51
+ }
52
+
53
+ rdo.each do |region|
54
+ region.dealers.each do |dealer|
55
+ dealer.offices.each do |office|
56
+ res[region.id] = { coords:[], props:[] } if res[region.id].nil?
57
+
58
+ # координаты точки (это массив двух точек)
59
+ gps = office.gps_arr
60
+
61
+ # соберём свойства офиса для балуна
62
+ props = {
63
+ balloonContentHeader: t = "#{office.title} (#{dealer.title})",
64
+ balloonContentBody: b = "#{office.addr}<br>#{office.tel}<br>GPS: #{office.gps}",
65
+ hintContent: "#{t}<br>#{b}",
66
+ id: office.id
67
+ }
68
+
69
+ # фиксируем в хэше региона
70
+ res[region.id][:coords] << gps
71
+ res[region.id][:props] << props
72
+
73
+ # фиксируем в all-хэше
74
+ res[:all][:coords] << gps
75
+ res[:all][:props] << props
76
+
77
+ end
78
+ # для удобства в js: зафиксируем кол-во офисов региона
79
+ res[region.id][:count] = res[region.id][:coords].size
80
+ end
81
+ end
82
+
83
+ # для удобства в js: зафиксируем кол-во всех офисов
84
+ res[:all][:count] = res[:all][:coords].size
85
+
86
+ res
87
+ end
88
+
89
+ # соберёт хэш только тех регионов, в которых есть офисы
90
+ # например: {4=>{:id=>4, :title=>"Санкт-Петербург"}}
91
+ def prepare_regions_hash(rdo)
92
+ res = {}
93
+ rdo.each do |region|
94
+ region.dealers.each do |dealer|
95
+ dealer.offices.each do |office|
96
+ if res[region.id].nil?
97
+ res[region.id] = { id:region.id, title:region.title }
98
+ else
99
+ break
100
+ end
101
+ end
102
+ end
103
+ end
104
+ res
105
+ end
106
+
14
107
  end
15
108
  end
@@ -1,12 +1,14 @@
1
1
  module C80Push
2
2
  module PageDealers
3
- module PageDealersHelper
3
+ module DealersLeftListHelper
4
4
 
5
- # Выдать список Дилеров (включая Офисы),
6
- # разложенный по Регионам.
5
+ # Выдать html unordered nested list Дилеров (включая Офисы),
6
+ # разложенный по Регионам, построенный
7
+ # на основе данных +rdo+ - Regions-Dealers-Offices.
7
8
  # Список выводится слева от карты.
8
9
  # (**) Не выводим регионы, у которых нет дилеров.
9
10
  #
11
+ # Структура списка:
10
12
  # * Регион
11
13
  # * Дилер
12
14
  # * Офис 1
@@ -18,11 +20,11 @@ module C80Push
18
20
  # * сайт дилера
19
21
  # * email дилера
20
22
  #
21
- def render_ul_dealers_list
23
+ def render_ul_dealers_list(rdo)
22
24
 
23
25
  res = ''
24
26
 
25
- Region.includes(dealers: :offices).each do |region|
27
+ rdo.each do |region|
26
28
  r = "<h2 class='region_title'>#{region.title}</h2>"
27
29
  ds = ul_region_dealers(region)
28
30
  next if ds.blank? # (**)
@@ -57,7 +59,7 @@ module C80Push
57
59
  dealer.offices.each_with_index do |office|
58
60
  o = "<h4 class='office_title'>#{office.title}</h4>"
59
61
  o += ul_office_props(office)
60
- res += "<li class='li_office' id='office_#{office.id}'>#{o}</li>"
62
+ res += "<li class='li_office' id='office_#{office.id}' data-id='#{office.id}'>#{o}</li>"
61
63
  end
62
64
  res += "<li class='dealer_email'>#{dealer.email}</li>"
63
65
  res += "<li class='dealer_site'>#{dealer.site}</li>"
@@ -19,5 +19,9 @@ module C80Push
19
19
 
20
20
  validates :tel,
21
21
  :presence => true
22
+
23
+ def gps_arr
24
+ self.gps.split(',').map! { |c| c.to_f }
25
+ end
22
26
  end
23
27
  end
@@ -1,13 +1,15 @@
1
1
  <div class="c80_push_page_dealers">
2
2
 
3
3
  <div class="select_region_row">
4
-
4
+ <div class="select_wrapper">
5
+ <%= render 'c80_push/shared/select_region', regions: regions_list %>
6
+ </div>
5
7
  </div>
6
8
 
7
9
  <div class="bottom_row">
8
10
 
9
11
  <div class="dealers_list">
10
- <%= render_ul_dealers_list %>
12
+ <%= render_ul_dealers_list(rdo_list) %>
11
13
  </div>
12
14
 
13
15
  <div id="dealers_map_container">
@@ -18,4 +20,8 @@
18
20
 
19
21
  </div>
20
22
 
23
+ <script>
24
+ var offices = <%= ymap_hash.to_json.html_safe %>;
25
+ </script>
26
+
21
27
  <script src="https://api-maps.yandex.ru/2.1/?lang=ru_RU" type="text/javascript"></script>
@@ -0,0 +1,7 @@
1
+ <select id='select_region' class="selectpicker" data-width="400px" data-size="10">
2
+ <option value="all">Выберите регион</option>
3
+ <% regions.each_key do |k| %>
4
+ <% region = regions[k] %>
5
+ <option value="<%= region[:id] %>"><%= region[:title] %></option>
6
+ <% end %>
7
+ </select>
@@ -1,3 +1,3 @@
1
1
  module C80Push
2
- VERSION = '0.1.0.1'
2
+ VERSION = '0.1.0.2'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: c80_push
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.1
4
+ version: 0.1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - C80609A
@@ -40,7 +40,11 @@ files:
40
40
  - app/assets/config/c80_push_manifest.js
41
41
  - app/assets/javascripts/c80_push.js.coffee
42
42
  - app/assets/javascripts/c80_push/backend/dealers.js
43
- - app/assets/javascripts/c80_push/frontend/c80_push_page_dealers/init_yandex_map.js
43
+ - app/assets/javascripts/c80_push/frontend/c80_push_page_dealers/_dealers_left_list_clicks.js
44
+ - app/assets/javascripts/c80_push/frontend/c80_push_page_dealers/_dealers_left_list_filter.js
45
+ - app/assets/javascripts/c80_push/frontend/c80_push_page_dealers/_map_init.js
46
+ - app/assets/javascripts/c80_push/frontend/c80_push_page_dealers/_map_set_objects.js
47
+ - app/assets/javascripts/c80_push/frontend/c80_push_page_dealers/_select_region_init.js
44
48
  - app/assets/javascripts/c80_push/lib_backend/init.js
45
49
  - app/assets/javascripts/c80_push/lib_backend/init_select_picker.js
46
50
  - app/assets/javascripts/c80_push_backend.js.coffee
@@ -51,12 +55,13 @@ files:
51
55
  - app/assets/stylesheets/c80_push_backend.scss
52
56
  - app/helpers/c80_push/admin_helper.rb
53
57
  - app/helpers/c80_push/application_helper.rb
54
- - app/helpers/c80_push/page_dealers/page_dealers_helper.rb
58
+ - app/helpers/c80_push/page_dealers/dealers_left_list_helper.rb
55
59
  - app/models/c80_push/application_record.rb
56
60
  - app/models/c80_push/dealer.rb
57
61
  - app/models/c80_push/office.rb
58
62
  - app/models/c80_push/region.rb
59
63
  - app/views/c80_push/shared/_page_dealers.html.erb
64
+ - app/views/c80_push/shared/_select_region.html.erb
60
65
  - config/locales/dealer/ru.yml
61
66
  - config/locales/office/ru.yml
62
67
  - config/locales/region/ru.yml
@@ -1,13 +0,0 @@
1
- $(document).ready(function() {
2
-
3
- var dealers_map;
4
-
5
- ymaps.ready(function() {
6
- dealers_map = new ymaps.Map('dealers_map_container', {
7
- center: [55, 37],
8
- zoom: 10,
9
- controls: ['zoomControl']
10
- });
11
- });
12
-
13
- });