c80_estate 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +67 -0
- data/Rakefile +2 -0
- data/app/admin/c80_estate/areas.rb +56 -0
- data/app/admin/c80_estate/atypes.rb +44 -0
- data/app/admin/c80_estate/prop_names.rb +48 -0
- data/app/admin/c80_estate/properties.rb +38 -0
- data/app/admin/c80_estate/role_types.rb +40 -0
- data/app/admin/c80_estate/uoms.rb +33 -0
- data/app/assets/javascript/c80_estate/backend/admin/areas.js +423 -0
- data/app/assets/javascript/c80_estate/backend/init.js +36 -0
- data/app/assets/javascript/c80_estate/backend/init_selectpicker.js +6 -0
- data/app/assets/javascript/c80_estate/lib/jalert.js +16 -0
- data/app/assets/javascript/c80_estate_active_admin.js.coffee +4 -0
- data/app/assets/stylesheets/c80_estate/backend/admin_areas.scss +109 -0
- data/app/assets/stylesheets/c80_estate/backend/admin_users.scss +27 -0
- data/app/assets/stylesheets/c80_estate/backend/common.scss +3 -0
- data/app/assets/stylesheets/c80_estate/lib/mixins.scss +17 -0
- data/app/assets/stylesheets/c80_estate_active_admin.scss +2 -0
- data/app/controllers/c80_estate/ajax_controller.rb +17 -0
- data/app/models/c80_estate/aphoto.rb +6 -0
- data/app/models/c80_estate/area.rb +26 -0
- data/app/models/c80_estate/astatus.rb +6 -0
- data/app/models/c80_estate/atphoto.rb +6 -0
- data/app/models/c80_estate/atype.rb +132 -0
- data/app/models/c80_estate/comment.rb +7 -0
- data/app/models/c80_estate/item_prop.rb +70 -0
- data/app/models/c80_estate/owner.rb +62 -0
- data/app/models/c80_estate/pphoto.rb +5 -0
- data/app/models/c80_estate/prop_name.rb +19 -0
- data/app/models/c80_estate/property.rb +15 -0
- data/app/models/c80_estate/role.rb +6 -0
- data/app/models/c80_estate/role_type.rb +5 -0
- data/app/models/c80_estate/uom.rb +5 -0
- data/app/uploaders/c80_estate/aphoto_uploader.rb +21 -0
- data/app/uploaders/c80_estate/atphoto_uploader.rb +21 -0
- data/app/uploaders/c80_estate/pphoto_uploader.rb +21 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/c80_estate.gemspec +25 -0
- data/config/routes.rb +3 -0
- data/db/migrate/20160629033533_create_c80_estate_areas.rb +13 -0
- data/db/migrate/20160629033535_create_c80_estate_properties.rb +15 -0
- data/db/migrate/20160629034444_create_c80_prop_names.rb +12 -0
- data/db/migrate/20160629041414_create_c80_estate_uoms.rb +10 -0
- data/db/migrate/20160629090606_create_c80_estate_aphotos.rb +9 -0
- data/db/migrate/20160629091313_create_c80_estate_astatuses.rb +9 -0
- data/db/migrate/20160629092323_create_c80_item_props.rb +14 -0
- data/db/migrate/20160629093030_create_c80_estate_comments.rb +12 -0
- data/db/migrate/20160629100505_create_c80_atypes.rb +10 -0
- data/db/migrate/20160629205151_create_c80_estate_atphotos.rb +9 -0
- data/db/migrate/20160630012727_create_c80_estate_pphotos.rb +9 -0
- data/db/migrate/20160630013636_create_join_table_areas_astatuses.rb +12 -0
- data/db/migrate/20160630013737_create_join_table_atypes_prop_names.rb +12 -0
- data/db/migrate/20160704050000_create_c80_estate_role_types.rb +9 -0
- data/db/migrate/20160704063131_create_c80_estate_roles.rb +10 -0
- data/db/seeds/50_fill_uoms.rb.example +8 -0
- data/db/seeds/55_fill_prop_names.rb.example +51 -0
- data/db/seeds/60_fill_atypes.rb.example +29 -0
- data/lib/c80_estate.rb +8 -0
- data/lib/c80_estate/engine.rb +23 -0
- data/lib/c80_estate/version.rb +3 -0
- metadata +151 -0
@@ -0,0 +1,36 @@
|
|
1
|
+
// initialize your global object will all your model names
|
2
|
+
//YOUR_APP = {
|
3
|
+
//
|
4
|
+
//};
|
5
|
+
|
6
|
+
var fLoadingShow = function () {
|
7
|
+
$("body").append($('<div id="loading"></div>'));
|
8
|
+
};
|
9
|
+
|
10
|
+
var fLoadingHide = function () {
|
11
|
+
$("#loading").remove();
|
12
|
+
};
|
13
|
+
|
14
|
+
//jQuery(document).ready(function ($) {
|
15
|
+
// get the page action
|
16
|
+
//var action, model, b = $("body");
|
17
|
+
//if (b.hasClass("edit")) {
|
18
|
+
// action = "edit";
|
19
|
+
//} else if (b.hasClass("view")) {
|
20
|
+
// action = "view";
|
21
|
+
//} else if (b.hasClass("index")) {
|
22
|
+
// action = "index"
|
23
|
+
//} else if (b.hasClass("new")) {
|
24
|
+
// action = "new"
|
25
|
+
//}
|
26
|
+
//
|
27
|
+
//run the code specific to a model and an action
|
28
|
+
//for (var m in YOUR_APP) {
|
29
|
+
// if (b.hasClass("admin_" + m)) {
|
30
|
+
// if (YOUR_APP[m][action] && typeof YOUR_APP[m][action] == "function") {
|
31
|
+
// YOUR_APP[m][action]();
|
32
|
+
// break;
|
33
|
+
// }
|
34
|
+
// }
|
35
|
+
//}
|
36
|
+
//});
|
@@ -0,0 +1,16 @@
|
|
1
|
+
|
2
|
+
var jAlert = function (message) {
|
3
|
+
$('<div id="dialog" class="my-dialog" title="Ошибка"><p>'+message+'</p></div>').dialog({
|
4
|
+
dialogClass: "no-close",
|
5
|
+
modal: true,
|
6
|
+
buttons: [
|
7
|
+
{
|
8
|
+
text: "OK",
|
9
|
+
buttonClass: 'nn',
|
10
|
+
click: function() {
|
11
|
+
$( this ).dialog( "close" );
|
12
|
+
}
|
13
|
+
}
|
14
|
+
]
|
15
|
+
});
|
16
|
+
};
|
@@ -0,0 +1,109 @@
|
|
1
|
+
body.admin_areas {
|
2
|
+
&.edit, &.new {
|
3
|
+
|
4
|
+
select {
|
5
|
+
/*padding: 3px 10px 5px 10px;*/
|
6
|
+
}
|
7
|
+
|
8
|
+
input {
|
9
|
+
/*font-size: 12px;*/
|
10
|
+
}
|
11
|
+
|
12
|
+
// в этом контейнере живут fieldset-ы, каждый из которых соответствует одному свойству предмета
|
13
|
+
li.item_props {
|
14
|
+
padding-top: 0;
|
15
|
+
|
16
|
+
// прячем h3
|
17
|
+
h3 {
|
18
|
+
display: none;
|
19
|
+
}
|
20
|
+
// прячем сразу кнопку "Добавить Item prop"
|
21
|
+
a.has_many_add {
|
22
|
+
display: none;
|
23
|
+
}
|
24
|
+
// прячем кнопку "убрать свойство"
|
25
|
+
a.has_many_remove {
|
26
|
+
display: none;
|
27
|
+
}
|
28
|
+
|
29
|
+
// приводим в табличный вид внешний вид
|
30
|
+
fieldset {
|
31
|
+
margin: 0;
|
32
|
+
@include shdw(0.0);
|
33
|
+
border: none;
|
34
|
+
border-radius: 0;
|
35
|
+
|
36
|
+
// прячем лейблы
|
37
|
+
label {
|
38
|
+
display: none;
|
39
|
+
}
|
40
|
+
|
41
|
+
li.select, li.input {
|
42
|
+
float: left;
|
43
|
+
padding: 3px;
|
44
|
+
}
|
45
|
+
|
46
|
+
select {
|
47
|
+
text-align: right;
|
48
|
+
float: left;
|
49
|
+
&:disabled {
|
50
|
+
color: #4C4C4C;
|
51
|
+
}
|
52
|
+
}
|
53
|
+
input {
|
54
|
+
float: left;
|
55
|
+
width: 400px;
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
}
|
60
|
+
|
61
|
+
form fieldset > ol > li.boolean {
|
62
|
+
height: auto;
|
63
|
+
&#item_is_main_input {padding-bottom: 20px;padding-top: 0;}
|
64
|
+
&#item_is_sale_input {padding-bottom: 0;}
|
65
|
+
label {
|
66
|
+
font-weight: bold;
|
67
|
+
color: #5E6469;
|
68
|
+
}
|
69
|
+
}
|
70
|
+
|
71
|
+
p.inline-hints {
|
72
|
+
color: #74b1b2;
|
73
|
+
padding-left: 50px;
|
74
|
+
}
|
75
|
+
|
76
|
+
// спрячем артефакт
|
77
|
+
li#area_galleries_input {
|
78
|
+
fieldset.choices {
|
79
|
+
legend.label { display:none; }
|
80
|
+
}
|
81
|
+
}
|
82
|
+
|
83
|
+
li.has_many_container {
|
84
|
+
width: 80%;
|
85
|
+
float: right;
|
86
|
+
padding: 0;
|
87
|
+
|
88
|
+
&.aphotos {
|
89
|
+
fieldset.has_many_fields {
|
90
|
+
background-color: transparent;
|
91
|
+
box-shadow: none;
|
92
|
+
border: 1px solid #dddddd;
|
93
|
+
}
|
94
|
+
h3 {
|
95
|
+
display: none;
|
96
|
+
}
|
97
|
+
|
98
|
+
}
|
99
|
+
|
100
|
+
}
|
101
|
+
|
102
|
+
.fieldset_item_props {
|
103
|
+
background-color: white !important;
|
104
|
+
box-shadow: none !important;
|
105
|
+
legend { display: none !important; }
|
106
|
+
}
|
107
|
+
|
108
|
+
}
|
109
|
+
}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
body.admin_admin_users {
|
2
|
+
&.edit, &.new {
|
3
|
+
|
4
|
+
li.has_many_container {
|
5
|
+
|
6
|
+
&.roles {
|
7
|
+
|
8
|
+
fieldset.has_many_fields {
|
9
|
+
background-color: transparent;
|
10
|
+
box-shadow: none;
|
11
|
+
border: none;
|
12
|
+
|
13
|
+
}
|
14
|
+
|
15
|
+
h3 {
|
16
|
+
display: none;
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
}
|
21
|
+
|
22
|
+
a.has_many_add {
|
23
|
+
display: none;
|
24
|
+
}
|
25
|
+
|
26
|
+
}
|
27
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
@mixin shdw($val) {
|
2
|
+
-webkit-box-shadow: 0 0 7px 0 rgba(0, 0, 0, $val);
|
3
|
+
-moz-box-shadow: 0 0 7px 0 rgba(0, 0, 0, $val);
|
4
|
+
box-shadow: 0 0 7px 0 rgba(0, 0, 0, $val);
|
5
|
+
/* For IE 8 */
|
6
|
+
-ms-filter: "progid:DXImageTransform.Microsoft.Shadow(Strength=$val, Direction=135, Color='#000000')";
|
7
|
+
/* For IE 5.5 - 7 */
|
8
|
+
filter: progid:DXImageTransform.Microsoft.Shadow(Strength=$val, Direction=135, Color='#000000');
|
9
|
+
}
|
10
|
+
|
11
|
+
@mixin opacity($val) {
|
12
|
+
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=$val)";
|
13
|
+
filter: alpha(opacity=$val);
|
14
|
+
-moz-opacity:$val;
|
15
|
+
-khtml-opacity: $val;
|
16
|
+
opacity: $val;
|
17
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module C80Estate
|
2
|
+
class AjaxController < ActionController::Base
|
3
|
+
|
4
|
+
def get_atype_propnames
|
5
|
+
|
6
|
+
atype_id = request.params[:atype_id]
|
7
|
+
obj = Atype.get_propnames(atype_id)
|
8
|
+
|
9
|
+
respond_to do |format|
|
10
|
+
format.js { render json: obj, status: :ok }
|
11
|
+
# format.json
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module C80Estate
|
2
|
+
class Area < ActiveRecord::Base
|
3
|
+
belongs_to :property
|
4
|
+
belongs_to :atype
|
5
|
+
belongs_to :owner, :polymorphic => true
|
6
|
+
has_many :item_props, :dependent => :destroy
|
7
|
+
accepts_nested_attributes_for :item_props,
|
8
|
+
:reject_if => lambda { |attributes|
|
9
|
+
# puts "attributes:: #{attributes}"
|
10
|
+
# attributes:: {"value"=>"", "prop_name_id"=>""}
|
11
|
+
!attributes.present? || \
|
12
|
+
!attributes[:value].present? || \
|
13
|
+
!attributes[:prop_name_id].present?
|
14
|
+
},
|
15
|
+
:allow_destroy => true
|
16
|
+
has_many :aphotos, :dependent => :destroy # одна или несколько фоток
|
17
|
+
accepts_nested_attributes_for :aphotos,
|
18
|
+
:reject_if => lambda { |attributes|
|
19
|
+
!attributes.present?
|
20
|
+
},
|
21
|
+
:allow_destroy => true
|
22
|
+
has_many :comments, :dependent => :destroy # площадь можно прокомментировать
|
23
|
+
has_and_belongs_to_many :astatuses, # единственный статус: либо занята, либо свободна
|
24
|
+
:join_table => 'c80_estate_areas_astatuses'
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require "babosa"
|
2
|
+
|
3
|
+
module C80Estate
|
4
|
+
|
5
|
+
class Atype < ActiveRecord::Base
|
6
|
+
|
7
|
+
# http://stackoverflow.com/questions/9382708/rails-3-has-many-changed
|
8
|
+
has_and_belongs_to_many :prop_names,
|
9
|
+
:join_table => 'c80_estate_atypes_prop_names',
|
10
|
+
:after_add => :after_add_prop_names,
|
11
|
+
:after_remove => :after_remove_prop_names
|
12
|
+
|
13
|
+
has_many :areas, :dependent => :destroy
|
14
|
+
has_many :properties, :dependent => :destroy
|
15
|
+
has_many :atphotos, :dependent => :destroy # одна или несколько фоток
|
16
|
+
|
17
|
+
extend FriendlyId
|
18
|
+
friendly_id :slug_candidates, :use => :slugged
|
19
|
+
|
20
|
+
def slug_candidates
|
21
|
+
[:title] + Array.new(6) {|index| [:title, index+2]}
|
22
|
+
end
|
23
|
+
|
24
|
+
def normalize_friendly_id(input)
|
25
|
+
input.to_s.to_slug.normalize(transliterations: :russian).to_s
|
26
|
+
end
|
27
|
+
|
28
|
+
# • этот метод дёргает только StrsubcatSweeper
|
29
|
+
# • после вызова метода - значение сбрасывается в false
|
30
|
+
def prop_names_changed?
|
31
|
+
res = @mark_prop_names_changed
|
32
|
+
@mark_prop_names_changed = false
|
33
|
+
res
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_list_removed_props
|
37
|
+
@list_removed_props = [] unless @list_removed_props.present?
|
38
|
+
res = @list_removed_props
|
39
|
+
@list_removed_props = []
|
40
|
+
res
|
41
|
+
end
|
42
|
+
|
43
|
+
# выдать все характеристики, присущие данной категории, вместе с единицами измерений
|
44
|
+
def self.get_propnames(atype_id)
|
45
|
+
|
46
|
+
=begin
|
47
|
+
>> stdh_get_atype_propnames(1)
|
48
|
+
<stdh_get_atype_propnames> BEGIN
|
49
|
+
(0.2ms)
|
50
|
+
SELECT
|
51
|
+
`prop_names`.`id`,
|
52
|
+
`prop_names`.`title`,
|
53
|
+
`prop_names`.`is_excluded_from_filtering`,
|
54
|
+
`uoms`.`title` as uom_title
|
55
|
+
FROM `prop_names`
|
56
|
+
INNER JOIN `prop_names_atypes` ON `prop_names`.`id` = `prop_names_atypes`.`prop_name_id`
|
57
|
+
LEFT OUTER JOIN uoms ON uoms.id = prop_names.uom_id
|
58
|
+
WHERE `prop_names_atypes`.`atype_id` = 1;
|
59
|
+
|
60
|
+
{"id"=>18, "title"=>"Цена за шт.", "is_excluded_from_filtering"=>1, "uom_title"=>"руб"}
|
61
|
+
{"id"=>19, "title"=>"Цена за шт. (старая)", "is_excluded_from_filtering"=>1, "uom_title"=>"руб"}
|
62
|
+
{"id"=>20, "title"=>"Цена за м²", "is_excluded_from_filtering"=>1, "uom_title"=>"руб"}
|
63
|
+
{"id"=>21, "title"=>"Цена за м² (старая)", "is_excluded_from_filtering"=>1, "uom_title"=>"руб"}
|
64
|
+
{"id"=>23, "title"=>"Размер", "is_excluded_from_filtering"=>0, "uom_title"=>nil}
|
65
|
+
{"id"=>24, "title"=>"Страна", "is_excluded_from_filtering"=>0, "uom_title"=>nil}
|
66
|
+
{"id"=>25, "title"=>"Прочность на сжатие", "is_excluded_from_filtering"=>0, "uom_title"=>"кгс/см²"}
|
67
|
+
{"id"=>26, "title"=>"Коэффициент теплопроводности", "is_excluded_from_filtering"=>0, "uom_title"=>"Вт/м×°C"}
|
68
|
+
{"id"=>27, "title"=>"Марка по морозостойкости", "is_excluded_from_filtering"=>0, "uom_title"=>nil}
|
69
|
+
{"id"=>28, "title"=>"Водопоглощение", "is_excluded_from_filtering"=>0, "uom_title"=>"%"}
|
70
|
+
{"id"=>29, "title"=>"Цвет", "is_excluded_from_filtering"=>0, "uom_title"=>nil}
|
71
|
+
{"id"=>30, "title"=>"Пустотность", "is_excluded_from_filtering"=>0, "uom_title"=>nil}
|
72
|
+
{"id"=>31, "title"=>"Формовка", "is_excluded_from_filtering"=>0, "uom_title"=>nil}
|
73
|
+
{"id"=>32, "title"=>"Поверхность", "is_excluded_from_filtering"=>0, "uom_title"=>nil}
|
74
|
+
{"id"=>33, "title"=>"Вес", "is_excluded_from_filtering"=>0, "uom_title"=>nil}
|
75
|
+
{"id"=>34, "title"=>"Количество на поддоне", "is_excluded_from_filtering"=>1, "uom_title"=>"шт"}
|
76
|
+
{"id"=>35, "title"=>"Тип кирпича", "is_excluded_from_filtering"=>0, "uom_title"=>nil}
|
77
|
+
{"id"=>36, "title"=>"Производитель", "is_excluded_from_filtering"=>0, "uom_title"=>nil}
|
78
|
+
{"id"=>37, "title"=>"Артикул", "is_excluded_from_filtering"=>1, "uom_title"=>nil}
|
79
|
+
{"id"=>38, "title"=>"Формат", "is_excluded_from_filtering"=>0, "uom_title"=>nil}
|
80
|
+
<stdh_get_atype_propnames> END
|
81
|
+
=end
|
82
|
+
|
83
|
+
Rails.logger.debug "<Atype.get_propnames> BEGIN"
|
84
|
+
sql = "
|
85
|
+
SELECT
|
86
|
+
`c80_estate_prop_names`.`id`,
|
87
|
+
`c80_estate_prop_names`.`title`,
|
88
|
+
`c80_estate_prop_names`.`is_excluded_from_filtering`,
|
89
|
+
`c80_estate_uoms`.`title` as uom_title
|
90
|
+
FROM `c80_estate_prop_names`
|
91
|
+
INNER JOIN `c80_estate_atypes_prop_names` ON `c80_estate_prop_names`.`id` = `c80_estate_atypes_prop_names`.`prop_name_id`
|
92
|
+
LEFT OUTER JOIN `c80_estate_uoms` ON `c80_estate_uoms`.`id` = `c80_estate_prop_names`.`uom_id`
|
93
|
+
WHERE `c80_estate_atypes_prop_names`.`atype_id` = #{atype_id};
|
94
|
+
"
|
95
|
+
|
96
|
+
result = []
|
97
|
+
rows = ActiveRecord::Base.connection.execute(sql)
|
98
|
+
rows.each(:as => :hash) do |row|
|
99
|
+
result << row
|
100
|
+
end
|
101
|
+
|
102
|
+
Rails.logger.debug "<Atype.get_propnames> END"
|
103
|
+
result
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
|
109
|
+
# • Два метода after_add_prop_names и after_remove_prop_names
|
110
|
+
# слушают изменения prop_names, и, при их наличии,
|
111
|
+
# выставляют флаг mark_prop_names_changed в true.
|
112
|
+
# • Этот флаг вертает обратно в false
|
113
|
+
# метод after_update "чистильщика" StrsubcatSweeper.
|
114
|
+
|
115
|
+
def after_add_prop_names(prop_name)
|
116
|
+
unless new_record?
|
117
|
+
puts "<Strsubcat.after_add_prop_names>: #{prop_name.title}"
|
118
|
+
@mark_prop_names_changed = true
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def after_remove_prop_names(prop_name)
|
123
|
+
puts "<Strsubcat.after_remove_prop_names>: #{prop_name.title}"
|
124
|
+
@mark_prop_names_changed = true
|
125
|
+
@list_removed_props = [] unless @list_removed_props.present?
|
126
|
+
@list_removed_props << prop_name.id
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
|
132
|
+
end
|