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 +4 -4
- data/README.md +34 -0
- data/app/assets/javascripts/c80_push/frontend/c80_push_page_dealers/_dealers_left_list_clicks.js +50 -0
- data/app/assets/javascripts/c80_push/frontend/c80_push_page_dealers/_dealers_left_list_filter.js +14 -0
- data/app/assets/javascripts/c80_push/frontend/c80_push_page_dealers/_map_init.js +23 -0
- data/app/assets/javascripts/c80_push/frontend/c80_push_page_dealers/_map_set_objects.js +26 -0
- data/app/assets/javascripts/c80_push/frontend/c80_push_page_dealers/_select_region_init.js +20 -0
- data/app/assets/stylesheets/c80_push/c80_push_page_dealers/_layout.scss +6 -1
- data/app/assets/stylesheets/c80_push/c80_push_page_dealers/_style.scss +14 -1
- data/app/assets/stylesheets/c80_push/c80_push_page_dealers/map_dealers_list.scss +6 -0
- data/app/helpers/c80_push/application_helper.rb +93 -0
- data/app/helpers/c80_push/page_dealers/{page_dealers_helper.rb → dealers_left_list_helper.rb} +8 -6
- data/app/models/c80_push/office.rb +4 -0
- data/app/views/c80_push/shared/_page_dealers.html.erb +8 -2
- data/app/views/c80_push/shared/_select_region.html.erb +7 -0
- data/lib/c80_push/version.rb +1 -1
- metadata +8 -3
- data/app/assets/javascripts/c80_push/frontend/c80_push_page_dealers/init_yandex_map.js +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b4d991e9e1a4d40ab4a2788f801fc5bda42e61d2
|
4
|
+
data.tar.gz: 37d7c1a99822e278f8b2b4db16255fdd29a187a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
> Данный раздел представляет собой список компаний, у которых указаны
|
data/app/assets/javascripts/c80_push/frontend/c80_push_page_dealers/_dealers_left_list_clicks.js
ADDED
@@ -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);
|
data/app/assets/javascripts/c80_push/frontend/c80_push_page_dealers/_dealers_left_list_filter.js
ADDED
@@ -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);
|
@@ -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
|
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
|
data/app/helpers/c80_push/page_dealers/{page_dealers_helper.rb → dealers_left_list_helper.rb}
RENAMED
@@ -1,12 +1,14 @@
|
|
1
1
|
module C80Push
|
2
2
|
module PageDealers
|
3
|
-
module
|
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
|
-
|
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>"
|
@@ -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>
|
data/lib/c80_push/version.rb
CHANGED
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.
|
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/
|
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/
|
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
|