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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: aca313a4bd48d2e8e5c1d37b1e0c7544a7e100bb
|
4
|
+
data.tar.gz: fed41c35fe08c402368bda60135399b817b6e482
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 689a4c55920d460c884c02172edb1b4116069fc4fa90309cedb228e1fbc0b5676c29898c89eff48fb48acb1e9309cb2af643e0af87b023575a3e0aad516ec4b1
|
7
|
+
data.tar.gz: 3c0a30e95776515cf627c85f6dfc8339f2ec0a17b1b6445a2a430d081071c5a8a73b1e78eb59ff1e63e7523b517d042aa83fb0d29978c7cee9ec35548835c950
|
data/.gitignore
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, and in the interest of
|
4
|
+
fostering an open and welcoming community, we pledge to respect all people who
|
5
|
+
contribute through reporting issues, posting feature requests, updating
|
6
|
+
documentation, submitting pull requests or patches, and other activities.
|
7
|
+
|
8
|
+
We are committed to making participation in this project a harassment-free
|
9
|
+
experience for everyone, regardless of level of experience, gender, gender
|
10
|
+
identity and expression, sexual orientation, disability, personal appearance,
|
11
|
+
body size, race, ethnicity, age, religion, or nationality.
|
12
|
+
|
13
|
+
Examples of unacceptable behavior by participants include:
|
14
|
+
|
15
|
+
* The use of sexualized language or imagery
|
16
|
+
* Personal attacks
|
17
|
+
* Trolling or insulting/derogatory comments
|
18
|
+
* Public or private harassment
|
19
|
+
* Publishing other's private information, such as physical or electronic
|
20
|
+
addresses, without explicit permission
|
21
|
+
* Other unethical or unprofessional conduct
|
22
|
+
|
23
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
24
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
25
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
26
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
27
|
+
threatening, offensive, or harmful.
|
28
|
+
|
29
|
+
By adopting this Code of Conduct, project maintainers commit themselves to
|
30
|
+
fairly and consistently applying these principles to every aspect of managing
|
31
|
+
this project. Project maintainers who do not follow or enforce the Code of
|
32
|
+
Conduct may be permanently removed from the project team.
|
33
|
+
|
34
|
+
This code of conduct applies both within project spaces and in public spaces
|
35
|
+
when an individual is representing the project or its community.
|
36
|
+
|
37
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
38
|
+
reported by contacting a project maintainer at c080609a@gmail.com. All
|
39
|
+
complaints will be reviewed and investigated and will result in a response that
|
40
|
+
is deemed necessary and appropriate to the circumstances. Maintainers are
|
41
|
+
obligated to maintain confidentiality with regard to the reporter of an
|
42
|
+
incident.
|
43
|
+
|
44
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
45
|
+
version 1.3.0, available at
|
46
|
+
[http://contributor-covenant.org/version/1/3/0/][version]
|
47
|
+
|
48
|
+
[homepage]: http://contributor-covenant.org
|
49
|
+
[version]: http://contributor-covenant.org/version/1/3/0/
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 C80609A
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# C80Estate
|
2
|
+
|
3
|
+
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/c80_estate`. To experiment with that code, run `bin/console` for an interactive prompt.
|
4
|
+
|
5
|
+
TODO: Delete this and the text above, and describe your gem
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'c80_estate'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install c80_estate
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
```
|
26
|
+
#= require c80_estate_active_admin
|
27
|
+
```
|
28
|
+
|
29
|
+
|
30
|
+
### Requires
|
31
|
+
|
32
|
+
```
|
33
|
+
@import "bootstrap";
|
34
|
+
```
|
35
|
+
|
36
|
+
```
|
37
|
+
#= require bootstrap/dropdown
|
38
|
+
#= require bootstrap-select
|
39
|
+
```
|
40
|
+
|
41
|
+
|
42
|
+
```
|
43
|
+
gem 'friendly_id'
|
44
|
+
gem 'babosa'
|
45
|
+
gem 'bootstrap-select-rails'
|
46
|
+
```
|
47
|
+
|
48
|
+
### Seeds
|
49
|
+
|
50
|
+
Copy and rename example seeds files.
|
51
|
+
|
52
|
+
|
53
|
+
## Development
|
54
|
+
|
55
|
+
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
56
|
+
|
57
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
58
|
+
|
59
|
+
## Contributing
|
60
|
+
|
61
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/c80_estate. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
62
|
+
|
63
|
+
|
64
|
+
## License
|
65
|
+
|
66
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
67
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
ActiveAdmin.register C80Estate::Area, as: 'Area' do
|
2
|
+
|
3
|
+
# scope_to :current_admin_user, association_method: :sites_list
|
4
|
+
|
5
|
+
menu :label => "Площади"
|
6
|
+
|
7
|
+
permit_params :title,
|
8
|
+
:desc,
|
9
|
+
:owner_id,
|
10
|
+
:owner_type,
|
11
|
+
:atype_id,
|
12
|
+
:property_id,
|
13
|
+
:aphotos_attributes => [:id,:image,:_destroy],
|
14
|
+
:item_props_attributes => [:value, :_destroy, :prop_name_id, :id]
|
15
|
+
|
16
|
+
config.sort_order = 'id_asc'
|
17
|
+
|
18
|
+
index do
|
19
|
+
column :title
|
20
|
+
column :atype do |area|
|
21
|
+
area.atype.title
|
22
|
+
end
|
23
|
+
actions
|
24
|
+
end
|
25
|
+
|
26
|
+
form(:html => {:multipart => true}) do |f|
|
27
|
+
|
28
|
+
f.inputs 'Свойства' do
|
29
|
+
f.input :title
|
30
|
+
f.input :atype, :input_html => { :class => 'selectpicker', 'data-size' => "5", 'data-width' => '300px'}
|
31
|
+
f.input :property, :input_html => { :class => 'selectpicker', 'data-size' => "5", 'data-width' => '300px'}
|
32
|
+
f.input :desc, :as => :ckeditor
|
33
|
+
|
34
|
+
f.inputs "Характеристики" do
|
35
|
+
|
36
|
+
f.has_many :item_props, :allow_destroy => true do |item_prop|
|
37
|
+
item_prop.input :prop_name
|
38
|
+
item_prop.input :value
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
f.has_many :aphotos, :allow_destroy => true do |gp|
|
44
|
+
gp.input :image,
|
45
|
+
:as => :file,
|
46
|
+
:hint => image_tag(gp.object.image.thumb512)
|
47
|
+
end
|
48
|
+
|
49
|
+
f.input :owner_id, :input_html => { :value => current_admin_user.id }, as: :hidden
|
50
|
+
f.input :owner_type, :input_html => { :value => "AdminUser" }, as: :hidden
|
51
|
+
end
|
52
|
+
|
53
|
+
f.actions
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# ПОДкатегории строительных материалов
|
2
|
+
ActiveAdmin.register C80Estate::Atype, :as => 'Atype' do
|
3
|
+
|
4
|
+
menu :label => "Типы", :parent => "Настройки"
|
5
|
+
|
6
|
+
permit_params :title,
|
7
|
+
:slug,
|
8
|
+
:prop_name_ids => []
|
9
|
+
|
10
|
+
config.sort_order = 'id_asc'
|
11
|
+
|
12
|
+
# controller do
|
13
|
+
# cache_sweeper :strsubcat_sweeper, :only => [:update,:create,:destroy]
|
14
|
+
# end
|
15
|
+
|
16
|
+
# before_filter :skip_sidebar!, :only => :index
|
17
|
+
|
18
|
+
filter :title
|
19
|
+
|
20
|
+
# controller do
|
21
|
+
# cache_sweeper :suit_sweeper, :only => [:update,:create,:destroy]
|
22
|
+
# end
|
23
|
+
|
24
|
+
index do
|
25
|
+
selectable_column
|
26
|
+
id_column
|
27
|
+
column :title
|
28
|
+
actions
|
29
|
+
end
|
30
|
+
|
31
|
+
form(:html => {:multipart => true}) do |f|
|
32
|
+
|
33
|
+
f.inputs "Свойства" do
|
34
|
+
f.input :title
|
35
|
+
end
|
36
|
+
|
37
|
+
f.inputs "Характеристики, которыми описываются объекты недвижимости и площади этого типа", :class => 'collapsed' do
|
38
|
+
f.input :prop_names, :as => :check_boxes
|
39
|
+
end
|
40
|
+
|
41
|
+
f.actions
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
ActiveAdmin.register C80Estate::PropName, as: 'PropName' do
|
2
|
+
|
3
|
+
menu :label => "Имена свойств", :parent => "Настройки"
|
4
|
+
|
5
|
+
permit_params :title,
|
6
|
+
:uom_id,
|
7
|
+
:is_excluded_from_filtering,
|
8
|
+
:is_normal_price
|
9
|
+
|
10
|
+
config.sort_order = 'title_asc'
|
11
|
+
|
12
|
+
filter :title
|
13
|
+
filter :atypes
|
14
|
+
filter :is_excluded_from_filtering
|
15
|
+
filter :is_normal_price
|
16
|
+
|
17
|
+
# controller do
|
18
|
+
# cache_sweeper :suit_sweeper, :only => [:update,:create,:destroy]
|
19
|
+
# end
|
20
|
+
|
21
|
+
index do
|
22
|
+
# selectable_column
|
23
|
+
id_column
|
24
|
+
|
25
|
+
column :title
|
26
|
+
column :uom
|
27
|
+
column :is_excluded_from_filtering
|
28
|
+
column :is_normal_price
|
29
|
+
|
30
|
+
actions
|
31
|
+
end
|
32
|
+
|
33
|
+
form(:html => {:multipart => true}) do |f|
|
34
|
+
|
35
|
+
f.inputs "Свойства" do
|
36
|
+
f.input :title
|
37
|
+
f.input :uom, :input_html => { :class => 'selectpicker', 'data-size' => "5", 'data-width' => '300px'}
|
38
|
+
f.input :is_excluded_from_filtering,
|
39
|
+
:hint => "Если да, то это свойство не будет фигурировать в списке фильтрации".html_safe
|
40
|
+
|
41
|
+
f.input :is_normal_price,
|
42
|
+
:hint => "Является ли свойство ценой".html_safe
|
43
|
+
|
44
|
+
end
|
45
|
+
f.actions
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
ActiveAdmin.register C80Estate::Property, as: 'Property' do
|
2
|
+
|
3
|
+
# scope_to :current_admin_user, association_method: :sites_list
|
4
|
+
|
5
|
+
menu :label => "Объекты недвижимости"
|
6
|
+
|
7
|
+
permit_params :title,
|
8
|
+
:desc,
|
9
|
+
:address,
|
10
|
+
:latitude,
|
11
|
+
:longitude,
|
12
|
+
:atype_id,
|
13
|
+
:owner_id,
|
14
|
+
:owner_type
|
15
|
+
|
16
|
+
config.sort_order = 'id_asc'
|
17
|
+
|
18
|
+
index do
|
19
|
+
column :title
|
20
|
+
column :atype do |prop|
|
21
|
+
prop.atype.title
|
22
|
+
end
|
23
|
+
actions
|
24
|
+
end
|
25
|
+
|
26
|
+
form(:html => {:multipart => true}) do |f|
|
27
|
+
|
28
|
+
f.inputs 'Свойства' do
|
29
|
+
f.input :title
|
30
|
+
f.input :atype, :input_html => { :class => 'selectpicker', 'data-size' => "5", 'data-width' => '300px'}
|
31
|
+
f.input :owner_id, :input_html => { :value => current_admin_user.id }, as: :hidden
|
32
|
+
f.input :owner_type, :input_html => { :value => "AdminUser" }, as: :hidden
|
33
|
+
end
|
34
|
+
|
35
|
+
f.actions
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# ПОДкатегории строительных материалов
|
2
|
+
ActiveAdmin.register C80Estate::RoleType, :as => 'RoleType' do
|
3
|
+
|
4
|
+
menu :label => "Роли", :parent => "Настройки"
|
5
|
+
|
6
|
+
permit_params :title,
|
7
|
+
:desc
|
8
|
+
|
9
|
+
config.sort_order = 'id_asc'
|
10
|
+
|
11
|
+
# controller do
|
12
|
+
# cache_sweeper :strsubcat_sweeper, :only => [:update,:create,:destroy]
|
13
|
+
# end
|
14
|
+
|
15
|
+
# before_filter :skip_sidebar!, :only => :index
|
16
|
+
|
17
|
+
filter :title
|
18
|
+
|
19
|
+
# controller do
|
20
|
+
# cache_sweeper :suit_sweeper, :only => [:update,:create,:destroy]
|
21
|
+
# end
|
22
|
+
|
23
|
+
index do
|
24
|
+
selectable_column
|
25
|
+
id_column
|
26
|
+
column :title
|
27
|
+
actions
|
28
|
+
end
|
29
|
+
|
30
|
+
form(:html => {:multipart => true}) do |f|
|
31
|
+
|
32
|
+
f.inputs "Свойства" do
|
33
|
+
f.input :title
|
34
|
+
f.input :desc, input_html: { rows: 3 }
|
35
|
+
end
|
36
|
+
|
37
|
+
f.actions
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# единицы измерения
|
2
|
+
ActiveAdmin.register C80Estate::Uom, :as => 'Uom' do
|
3
|
+
|
4
|
+
menu :label => "Единицы измерения", :parent => "Настройки"
|
5
|
+
|
6
|
+
permit_params :title, :comment, :is_number
|
7
|
+
|
8
|
+
config.sort_order = 'title_desc'
|
9
|
+
|
10
|
+
filter :title
|
11
|
+
|
12
|
+
index do
|
13
|
+
# selectable_column
|
14
|
+
# id_column
|
15
|
+
|
16
|
+
column :title
|
17
|
+
column :comment
|
18
|
+
column :is_number
|
19
|
+
|
20
|
+
# actions
|
21
|
+
end
|
22
|
+
|
23
|
+
form(:html => {:multipart => true}) do |f|
|
24
|
+
|
25
|
+
f.inputs "Свойства" do
|
26
|
+
f.input :title
|
27
|
+
f.input :comment
|
28
|
+
f.input :is_number
|
29
|
+
end
|
30
|
+
f.actions
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,423 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
// защита от неправильных данных
|
4
|
+
var fCheckItemProperties = function () {
|
5
|
+
|
6
|
+
var result = true;
|
7
|
+
|
8
|
+
// - название
|
9
|
+
if ($("input#area_title").val().length == 0) {
|
10
|
+
jAlert('Укажите название.');
|
11
|
+
result = false;
|
12
|
+
}
|
13
|
+
|
14
|
+
// - тип
|
15
|
+
if ($("select#area_atype_id").val() == "") {
|
16
|
+
jAlert('Укажите тип.');
|
17
|
+
result = false;
|
18
|
+
}
|
19
|
+
|
20
|
+
var item_props_input_list = $("li.item_props").find("input");
|
21
|
+
var inputs_count = item_props_input_list.length;
|
22
|
+
|
23
|
+
// - заполнение всех свойств
|
24
|
+
if (inputs_count == 0) {
|
25
|
+
result = false;
|
26
|
+
jAlert('Не получится создать площадь без свойств.');
|
27
|
+
} else {
|
28
|
+
item_props_input_list.each(function () {
|
29
|
+
if ($(this).val() != '') {
|
30
|
+
inputs_count--;
|
31
|
+
}
|
32
|
+
});
|
33
|
+
if (inputs_count > 0) {
|
34
|
+
result = false;
|
35
|
+
jAlert('Заполните все свойства площади.');
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
return result;
|
40
|
+
};
|
41
|
+
|
42
|
+
var jsinit = {
|
43
|
+
|
44
|
+
_debug:true,
|
45
|
+
$select_atype: null,
|
46
|
+
$btn_add_area_prop: null, // кнопка "Добавить "
|
47
|
+
$item_props_container: null, // в этом контейнере живут fieldset-ы, каждый из которых соответствует одному свойству предмета
|
48
|
+
$item_props_container_span: null, // заголовок контейнера, в котором живут fieldset-ы свойств предмета
|
49
|
+
|
50
|
+
// допишем поясняющий текст "сначала выберите подкатегорию"
|
51
|
+
_fWelcomeTextAdd: function () {
|
52
|
+
jsinit.$item_props_container_span.text("Характеристики [сначала выберите подкатегорию, тогда появятся свойства, присущие выбранной категории]");
|
53
|
+
},
|
54
|
+
|
55
|
+
// удалим поясняющий текст "сначала выберите подкатегорию"
|
56
|
+
_fWelcomeTextRemove: function () {
|
57
|
+
jsinit.$item_props_container_span.text("Характеристики");
|
58
|
+
},
|
59
|
+
|
60
|
+
go: function () {
|
61
|
+
//jsinit._log("[go]");
|
62
|
+
alert('go');
|
63
|
+
|
64
|
+
// фиксируем селект "Тип площади"
|
65
|
+
jsinit.$select_atype = $("select#area_atype_id");
|
66
|
+
|
67
|
+
// фиксируем контейнер, в котором находятся компоненты для управления свойством C80Estate::Area
|
68
|
+
jsinit.$item_props_container = $("li.item_props");
|
69
|
+
|
70
|
+
jsinit.$item_props_container.parent().parent().addClass('fieldset_item_props');
|
71
|
+
|
72
|
+
// фиксируем надпись "Характеристики"
|
73
|
+
jsinit.$item_props_container_span = jsinit.$item_props_container.parent().parent().find("> legend > span");
|
74
|
+
|
75
|
+
// фиксируем кнопку "Добавить свойство"
|
76
|
+
jsinit.$btn_add_area_prop = jsinit.$item_props_container.find("a.has_many_add");
|
77
|
+
|
78
|
+
// фиксируем кнопку "Update/Create"
|
79
|
+
jsinit.$btn_submin = $("fieldset.actions").find("input[name=commit]");
|
80
|
+
|
81
|
+
// начинаем слушать изменение селекта "тип" -
|
82
|
+
jsinit.$select_atype.on("change", jsinit._onSelectStrSubcatChange);
|
83
|
+
jsinit._onSelectStrSubcatChange();
|
84
|
+
|
85
|
+
// в момент нажатия кнопки "отправить" - "разлачиваем" все селекты
|
86
|
+
jsinit.$btn_submin.click(function (e) {
|
87
|
+
if (fCheckItemProperties()) {
|
88
|
+
jsinit.$item_props_container.find("select").attr("disabled", false);
|
89
|
+
fLoadingShow();
|
90
|
+
} else {
|
91
|
+
e.preventDefault();
|
92
|
+
}
|
93
|
+
});
|
94
|
+
|
95
|
+
// пока пользователь не выбрал подкатегорию - допишем поясняющий текст "сначала выберите подкатегорию"
|
96
|
+
jsinit._fWelcomeTextAdd();
|
97
|
+
|
98
|
+
},
|
99
|
+
|
100
|
+
// слушает изменения селекта с типами
|
101
|
+
// инициирует запрос за "Именами Свойств" выбранного в селекте "Типа"
|
102
|
+
// показывает загрузчик
|
103
|
+
_onSelectStrSubcatChange: function () {
|
104
|
+
var atype_id = jsinit.$select_atype[0].value;
|
105
|
+
//jsinit._log("[_onSelectStrSubcatChange]: atype_id = " + atype_id);
|
106
|
+
if (atype_id == '') {
|
107
|
+
jsinit._removeMayBeAddedProps();
|
108
|
+
jsinit._fWelcomeTextAdd();
|
109
|
+
} else {
|
110
|
+
fLoadingShow();
|
111
|
+
jsinit._reqStrsubcatPropnames(atype_id);
|
112
|
+
jsinit._fWelcomeTextRemove();
|
113
|
+
}
|
114
|
+
},
|
115
|
+
|
116
|
+
// запрашиваем список имён свойств указанной подкатегории
|
117
|
+
_reqStrsubcatPropnames: function (atype_id) {
|
118
|
+
//jsinit._log("[_reqStrsubcatPropnames]: atype_id = " + atype_id);
|
119
|
+
|
120
|
+
$.ajax({
|
121
|
+
url: "/estate/get_atype_propnames",
|
122
|
+
data: { atype_id:atype_id },
|
123
|
+
dataType: "json",
|
124
|
+
type: 'POST'
|
125
|
+
}).done(function(data,result) {
|
126
|
+
//jsinit._log( data );
|
127
|
+
|
128
|
+
if (result == "success") {
|
129
|
+
jsinit._log( "Кол-во свойств: " + data.length );
|
130
|
+
|
131
|
+
// удалим, возможно уже добавленные в форму, свойства
|
132
|
+
jsinit._removeMayBeAddedProps();
|
133
|
+
|
134
|
+
// количество свойств
|
135
|
+
var n = data.length;
|
136
|
+
|
137
|
+
// "цикловые" переменные
|
138
|
+
var $ifs, // fieldset,
|
139
|
+
$iselprop, // очередной селект "имя свойства"
|
140
|
+
$iinputprop, // очередной input "значение свойства"
|
141
|
+
$ifindbyid, // вспомогательная переменная: содержит результат поиска по id с помощью регулярки
|
142
|
+
ielem; // очередной элемент из data
|
143
|
+
|
144
|
+
for (var i=0; i<n; i++) {
|
145
|
+
|
146
|
+
// фиксируем объект с данными, описывающий свойство предмета
|
147
|
+
ielem = data[i];
|
148
|
+
|
149
|
+
// нажмём кнопку "Добавить Item prop"
|
150
|
+
jsinit.$btn_add_area_prop.click();
|
151
|
+
|
152
|
+
// фиксируем добавленный в форму fieldset
|
153
|
+
|
154
|
+
//<fieldset class="inputs has_many_fields processed">
|
155
|
+
// <ol>
|
156
|
+
// <li id="area_item_props_attributes_37_prop_name_input">
|
157
|
+
// <select id="area_item_props_attributes_37_prop_name_id">
|
158
|
+
// <option value="37">Артикул</option>
|
159
|
+
// </select>
|
160
|
+
// </li>
|
161
|
+
// <li id="area_item_props_attributes_37_value_input">
|
162
|
+
// <input id="area_item_props_attributes_37_value" type="text">
|
163
|
+
// </li>
|
164
|
+
// </ol>
|
165
|
+
//</fieldset>
|
166
|
+
|
167
|
+
$ifs = jsinit.$item_props_container.find("fieldset").not(".processed");
|
168
|
+
$ifs.addClass("processed");
|
169
|
+
|
170
|
+
$ifindbyid = $ifs.find('[id^="area_item_props_attributes_"]');
|
171
|
+
|
172
|
+
// находим в ifs селект, отвечающий за имя свойства
|
173
|
+
$iselprop = $ifindbyid.find('select');
|
174
|
+
//console.log(iselprop);
|
175
|
+
|
176
|
+
// находим в ifs input, отвечающий за значение свойства
|
177
|
+
$iinputprop = $ifindbyid.find('input');
|
178
|
+
|
179
|
+
// в этот селект жестоко предустанавливаем значение из data, дописываем единицу измерения
|
180
|
+
$iselprop.find("option")
|
181
|
+
.filter(function () {
|
182
|
+
//console.log($(this).val() + " vs " + ielem["id"]);
|
183
|
+
return $(this).val() == ielem["id"]; //return $(this).text() == ielem["title"];
|
184
|
+
})
|
185
|
+
.prop('selected', true)
|
186
|
+
.text(function () {
|
187
|
+
var t = $(this).text();
|
188
|
+
if (ielem["uom_title"] != null) {
|
189
|
+
t += ", " + ielem["uom_title"];
|
190
|
+
}
|
191
|
+
return t;
|
192
|
+
}); // дописываем в конец единицу измерения
|
193
|
+
|
194
|
+
//делаем его readonly
|
195
|
+
$iselprop.attr("disabled", true); // NOTE:: но в момент нажатия кнопки "Отправить" мы "разлачиваем" селект, чтобы параметры формы "правильно" отправлялись;
|
196
|
+
|
197
|
+
// в input "производитель" - ставим "-1" и прячем его от пользователя
|
198
|
+
if (ielem["id"] == 36) {
|
199
|
+
$iinputprop.val("-1");
|
200
|
+
$ifs.css("display",'none');
|
201
|
+
}
|
202
|
+
|
203
|
+
}
|
204
|
+
|
205
|
+
fLoadingHide();
|
206
|
+
|
207
|
+
} else {
|
208
|
+
alert( "done: не удалось получить данные о свойствах выбранной подкатегории." );
|
209
|
+
}
|
210
|
+
|
211
|
+
})
|
212
|
+
.fail(function(jqXHR, textStatus) {
|
213
|
+
alert( "fail: не удалось получить данные о свойствах выбранной подкатегории: " + textStatus );
|
214
|
+
})
|
215
|
+
.always(function() {
|
216
|
+
//alert( "complete" );
|
217
|
+
});
|
218
|
+
},
|
219
|
+
|
220
|
+
// удалим, возможно уже добавленные в форму, свойства
|
221
|
+
_removeMayBeAddedProps: function () {
|
222
|
+
$("a.has_many_remove").click();
|
223
|
+
},
|
224
|
+
|
225
|
+
_log: function () {
|
226
|
+
if (jsinit._debug) {
|
227
|
+
//console.log(arguments[0]);
|
228
|
+
}
|
229
|
+
}
|
230
|
+
|
231
|
+
};
|
232
|
+
|
233
|
+
var fEdit = function () {
|
234
|
+
|
235
|
+
var $select_area_atype; // селект подкатегории, которой принадлежит редактируемый предмет
|
236
|
+
var $item_props_container; // здесь живут селекты свойств
|
237
|
+
var $btn_submit;
|
238
|
+
var atype_id; // id подкатегории, которой принадлежит редактируемый предмет, извлекается из селекта $select_area_atype
|
239
|
+
var $btn_add_area_prop; // кнопка "добавить свойство"
|
240
|
+
|
241
|
+
// вернёт true, если найдёт в $item_props_container селект свойства atype_id
|
242
|
+
var _fCheckSelect = function (atype_id) {
|
243
|
+
var result = false;
|
244
|
+
var $selects = $item_props_container.find("fieldset").find('select');
|
245
|
+
$selects.each(function () {
|
246
|
+
if ($(this).val() == atype_id) {
|
247
|
+
result = true;
|
248
|
+
}
|
249
|
+
});
|
250
|
+
return result;
|
251
|
+
};
|
252
|
+
|
253
|
+
var fReqPropList = function (atype_id) {
|
254
|
+
$.ajax({
|
255
|
+
url: "/estate/get_atype_propnames",
|
256
|
+
data: { atype_id:atype_id },
|
257
|
+
dataType: "json",
|
258
|
+
type: 'POST'
|
259
|
+
}).done(function (data,result) {
|
260
|
+
//data - это список свойств, которые должны быть у предмета
|
261
|
+
if (result == "success") {
|
262
|
+
|
263
|
+
/* обходим data, ищем соответствующие селекты,
|
264
|
+
* по ходу формируем список toAdd - индексы массива data
|
265
|
+
* отсутствующих свойств. Затем обрабатываем
|
266
|
+
* получившийся список и добавляем отсутствующие селекты. */
|
267
|
+
|
268
|
+
var toAdd = [];
|
269
|
+
|
270
|
+
// количество свойств
|
271
|
+
var n = data.length;
|
272
|
+
|
273
|
+
var ielem;
|
274
|
+
|
275
|
+
// обходим список свойств, которые должны быть у предмета
|
276
|
+
// и выясняем, кто отсутствует в форме
|
277
|
+
for (var i=0; i<n; i++) {
|
278
|
+
|
279
|
+
// фиксируем объект с данными
|
280
|
+
ielem = data[i];
|
281
|
+
|
282
|
+
// если такой селекта нет в форме - запомним id свойства
|
283
|
+
if (_fCheckSelect(ielem["id"])) {
|
284
|
+
|
285
|
+
} else {
|
286
|
+
toAdd.push(i);
|
287
|
+
}
|
288
|
+
}
|
289
|
+
|
290
|
+
var $ifs, $iselprop;
|
291
|
+
|
292
|
+
// теперь добавляем отсутствующие селекты
|
293
|
+
n = toAdd.length;
|
294
|
+
for (i = 0; i<n; i++) {
|
295
|
+
ielem = data[ toAdd[i] ];
|
296
|
+
|
297
|
+
// нажмём кнопку "Добавить Item prop"
|
298
|
+
$btn_add_area_prop.click();
|
299
|
+
|
300
|
+
// фиксируем добавленный в форму fieldset
|
301
|
+
$ifs = $item_props_container.find("fieldset").not(".was_before");
|
302
|
+
$ifs.addClass("was_before");
|
303
|
+
|
304
|
+
// находим в ifs селект, отвечающий за имя свойства
|
305
|
+
$iselprop = $ifs.find('[id^="area_item_props_attributes_"]').find('select');
|
306
|
+
|
307
|
+
// в этот селект жестоко предустанавливаем значение из data и делаем его readonly
|
308
|
+
$iselprop.find("option").filter(function () {
|
309
|
+
//console.log(this);
|
310
|
+
return $(this).val() == ielem["id"]; //return $(this).text() == ielem["title"];
|
311
|
+
}).prop('selected', true);
|
312
|
+
$iselprop.attr("disabled", true); // NOTE:: но в момент нажатия кнопки "Отправить" мы "разлачиваем" селект, чтобы параметры формы "правильно" отправлялись
|
313
|
+
|
314
|
+
}
|
315
|
+
|
316
|
+
/*дописываем единицы измерения всем селектам*/
|
317
|
+
|
318
|
+
// перед циклом: фиксируем все fieldset
|
319
|
+
$ifs = $item_props_container.find("fieldset");
|
320
|
+
|
321
|
+
// перед циклом: фиксируем все интерактивные элементы с таким id
|
322
|
+
var $ifindbyid = $ifs.find('[id^="area_item_props_attributes_"]');
|
323
|
+
$iselprop = $ifindbyid.find('select');
|
324
|
+
|
325
|
+
n = data.length;
|
326
|
+
for (i = 0; i<n; i++) {
|
327
|
+
ielem = data[i];
|
328
|
+
|
329
|
+
// находим селект, отвечающий за имя свойства и дописываем единицу измерения
|
330
|
+
$iselprop.find("option").filter(function () {
|
331
|
+
//console.log(this);
|
332
|
+
return $(this).val() == ielem["id"]; //return $(this).text() == ielem["title"];
|
333
|
+
}).text(function () {
|
334
|
+
var t = $(this).text();
|
335
|
+
if (ielem["uom_title"] != null) {
|
336
|
+
t += ", " + ielem["uom_title"]
|
337
|
+
}
|
338
|
+
return t;
|
339
|
+
});
|
340
|
+
|
341
|
+
// в input "производитель" - ставим "-1" и прячем весь fieldset от пользователя
|
342
|
+
if (ielem["id"] == 36) {
|
343
|
+
// находим опцию id=36 селекта "имя свойства"
|
344
|
+
var $opt = $iselprop.find("option").filter(function () {
|
345
|
+
var $t = $(this);
|
346
|
+
return $t.val() == 36 && $t.prop('selected');
|
347
|
+
});
|
348
|
+
// из этой опции добираемся до fieldset, который её содержит
|
349
|
+
var $fieldset = $opt.parent().parent().parent();
|
350
|
+
// а затем уже находим input
|
351
|
+
$fieldset.find("input").val("-1");
|
352
|
+
// прячем
|
353
|
+
$fieldset.css('display','none');
|
354
|
+
|
355
|
+
}
|
356
|
+
|
357
|
+
}
|
358
|
+
|
359
|
+
fLoadingHide();
|
360
|
+
|
361
|
+
} else {
|
362
|
+
alert( "done: не удалось получить данные о свойствах выбранной подкатегории." );
|
363
|
+
}
|
364
|
+
}).fail(function(jqXHR, textStatus) {
|
365
|
+
alert( "fail: не удалось получить данные о свойствах выбранной подкатегории: " + textStatus );
|
366
|
+
});
|
367
|
+
};
|
368
|
+
|
369
|
+
$(document).ready(function () {
|
370
|
+
|
371
|
+
// инициализация
|
372
|
+
|
373
|
+
// фиксируем селект "Тип площади"
|
374
|
+
$select_area_atype = $('select#area_atype_id');
|
375
|
+
// заодно запомним, какой тип установленен для текущей редактируемой площади
|
376
|
+
atype_id = $select_area_atype[0].value;
|
377
|
+
|
378
|
+
// фиксируем кнопку "Update/Create"
|
379
|
+
$btn_submit = $("fieldset.actions").find("input[name=commit]");
|
380
|
+
|
381
|
+
// фиксируем контейнер, в котором находятся компоненты для управления свойством C80Estate::Area
|
382
|
+
$item_props_container = $("li.item_props");
|
383
|
+
|
384
|
+
$item_props_container.parent().parent().addClass('fieldset_item_props');
|
385
|
+
|
386
|
+
// фиксируем кнопку "Добавить свойство"
|
387
|
+
$btn_add_area_prop = $item_props_container.find("a.has_many_add");
|
388
|
+
|
389
|
+
// блокируем селект "тип"
|
390
|
+
$select_area_atype.attr("disabled", true);
|
391
|
+
|
392
|
+
// блокируем селекты "свойства товара"
|
393
|
+
$item_props_container.find("select").attr("disabled", true);
|
394
|
+
|
395
|
+
// отмечаем уже имеющиеся fieldsets
|
396
|
+
$item_props_container.find("fieldset").each(function () {
|
397
|
+
$(this).addClass("was_before");
|
398
|
+
});
|
399
|
+
|
400
|
+
//совершаем запрос за свойствами, которые присущи данному типу
|
401
|
+
fReqPropList(atype_id);
|
402
|
+
|
403
|
+
// в момент нажатия кнопки "отправить" - "разлачиваем" все селекты
|
404
|
+
// и добавляем модальный предзагрузчик
|
405
|
+
$btn_submit.click(function (e) {
|
406
|
+
if (fCheckItemProperties()) {
|
407
|
+
$item_props_container.find("select").attr("disabled", false);
|
408
|
+
fLoadingShow();
|
409
|
+
//e.preventDefault(); // for debug
|
410
|
+
} else {
|
411
|
+
e.preventDefault();
|
412
|
+
}
|
413
|
+
});
|
414
|
+
|
415
|
+
});
|
416
|
+
|
417
|
+
fLoadingShow();
|
418
|
+
};
|
419
|
+
|
420
|
+
YOUR_APP.areas = {
|
421
|
+
edit: fEdit,
|
422
|
+
"new": jsinit.go
|
423
|
+
};
|