sofav 0.2.0

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 (71) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +35 -0
  4. data/Rakefile +34 -0
  5. data/app/builders/admin/form_builder.rb +250 -0
  6. data/app/controllers/application_controller.rb +23 -0
  7. data/app/decorators/base_decorator.rb +172 -0
  8. data/app/helpers/admin/core_helper.rb +237 -0
  9. data/app/helpers/admin/show_view_helper.rb +69 -0
  10. data/app/helpers/admin/tags_helper.rb +104 -0
  11. data/app/services/active_record/search_service.rb +121 -0
  12. data/app/views/admin/application/_breadcrumb_nav.html.erb +10 -0
  13. data/app/views/admin/application/_collection.html.erb +79 -0
  14. data/app/views/admin/application/_save_js.js.erb +20 -0
  15. data/app/views/admin/application/_sidebar.html.erb +62 -0
  16. data/app/views/admin/application/_topbar.html.erb +32 -0
  17. data/app/views/admin/application/actions/charge.html.erb +3 -0
  18. data/app/views/admin/application/actions/destroy.html.erb +5 -0
  19. data/app/views/admin/application/actions/edit.html.erb +1 -0
  20. data/app/views/admin/application/actions/edit_sights.html.erb +1 -0
  21. data/app/views/admin/application/actions/feedback.html.erb +4 -0
  22. data/app/views/admin/application/actions/index_charge.html.erb +1 -0
  23. data/app/views/admin/application/actions/index_destroy.html.erb +1 -0
  24. data/app/views/admin/application/actions/index_edit.html.erb +1 -0
  25. data/app/views/admin/application/actions/index_edit_sights.html.erb +1 -0
  26. data/app/views/admin/application/actions/index_show.html.erb +1 -0
  27. data/app/views/admin/application/actions/new.html.erb +1 -0
  28. data/app/views/admin/application/create.js.erb +1 -0
  29. data/app/views/admin/application/destroy.js.erb +6 -0
  30. data/app/views/admin/application/edit.html.erb +18 -0
  31. data/app/views/admin/application/index.html.erb +23 -0
  32. data/app/views/admin/application/new.html.erb +18 -0
  33. data/app/views/admin/application/partials/_map_pos_picker.html.erb +101 -0
  34. data/app/views/admin/application/partials/_sort_script.html.erb +32 -0
  35. data/app/views/admin/application/show.html.erb +16 -0
  36. data/app/views/admin/application/update.js.erb +1 -0
  37. data/app/views/admin/dashboard/index.html.erb +8 -0
  38. data/app/views/layouts/admin.html.erb +30 -0
  39. data/config/locales/devise.en.yml +64 -0
  40. data/config/locales/devise.zh-CN.yml +120 -0
  41. data/config/locales/doorkeeper.en.yml +124 -0
  42. data/config/locales/doorkeeper.zh-CN.yml +132 -0
  43. data/config/locales/en.yml +23 -0
  44. data/config/locales/enumerize/defaults.zh-CN.yml +7 -0
  45. data/config/locales/kaminari.zh-CN.yml +17 -0
  46. data/config/locales/rails.zh-CN.yml +204 -0
  47. data/config/locales/views/actions.zh-CN.yml +21 -0
  48. data/config/locales/views/attributes.zh-CN.yml +15 -0
  49. data/config/locales/views/breadcrumb.zh-CN.yml +5 -0
  50. data/config/locales/views/common.zh-CN.yml +7 -0
  51. data/config/locales/views/enums.zh-CN.yml +13 -0
  52. data/config/locales/views/profiles.zh-CN.yml +3 -0
  53. data/lib/generators/sofav/USAGE +0 -0
  54. data/lib/generators/sofav/sofav_generator.rb +50 -0
  55. data/lib/generators/sofav/templates/activerecord.zh-CN.yml +4 -0
  56. data/lib/generators/sofav/templates/attribute_types.zh-CN.yml +2 -0
  57. data/lib/sofav.rb +6 -0
  58. data/lib/sofav/decorator.rb +47 -0
  59. data/lib/sofav/local.rb +52 -0
  60. data/lib/sofav/version.rb +3 -0
  61. data/lib/tasks/sofa_tasks.rake +4 -0
  62. data/vendor/assets/javascripts/admin/here.js +0 -0
  63. data/vendor/assets/javascripts/bootbox.js +1020 -0
  64. data/vendor/assets/javascripts/bootstrap.js +2377 -0
  65. data/vendor/assets/javascripts/jquery-ui.js +5169 -0
  66. data/vendor/assets/javascripts/select2.js +5725 -0
  67. data/vendor/assets/stylesheets/bootstrap.css +6800 -0
  68. data/vendor/assets/stylesheets/bootstrap.css.map +1 -0
  69. data/vendor/assets/stylesheets/jquery-ui.css +453 -0
  70. data/vendor/assets/stylesheets/select2.css +484 -0
  71. metadata +211 -0
@@ -0,0 +1,10 @@
1
+ <section class="breadcrumb-nav clearfix">
2
+ <ol class="breadcrumb">
3
+ <li>
4
+ <%= link_to(controller.controller_name_human, url_for(controller: controller_path)) %>
5
+ </li>
6
+ <li class="active">
7
+ <%= link_to(controller.action_name_human(action_name), 'javascript:;', class: 'active') %>
8
+ </li>
9
+ </ol>
10
+ </section>
@@ -0,0 +1,79 @@
1
+ <%#
2
+ # Collection
3
+
4
+ This partial is used on the `index` and `show` pages
5
+ to display a collection of resources in an HTML table.
6
+
7
+ ## Local variables:
8
+
9
+ - `collection_presenter`:
10
+ An instance of [Administrate::Page::Collection][1].
11
+ The table presenter uses `ResourceDashboard::COLLECTION_ATTRIBUTES` to determine
12
+ the columns displayed in the table
13
+ - `resources`:
14
+ An ActiveModel::Relation collection of resources to be displayed in the table.
15
+ By default, the number of resources is limited by pagination
16
+ or by a hard limit to prevent excessive page load times
17
+
18
+ [1]: http://www.rubydoc.info/gems/administrate/Administrate/Page/Collection
19
+ %>
20
+
21
+ <table class="collection-data" aria-labelledby="page-title">
22
+ <thead>
23
+ <tr>
24
+ <% collection_presenter.attribute_types.each do |attr_name, attr_type| %>
25
+ <th class="cell-label cell-label--<%= attr_type.html_class %>
26
+ cell-label--<%= collection_presenter.ordered_html_class(attr_name) %>
27
+ " scope="col">
28
+ <%= link_to(params.merge(
29
+ collection_presenter.order_params_for(attr_name)
30
+ )) do %>
31
+ <%= attr_name.to_s.titleize %>
32
+
33
+ <% if collection_presenter.ordered_by?(attr_name) %>
34
+ <span class="cell-label__sort-indicator cell-label__sort-indicator--<%= collection_presenter.ordered_html_class(attr_name) %>">
35
+ <%= svg_tag(
36
+ "administrate/sort_arrow.svg",
37
+ "sort_arrow",
38
+ width: "13",
39
+ height: "13"
40
+ ) %>
41
+ </span>
42
+ <% end %>
43
+ <% end %>
44
+ </th>
45
+ <% end %>
46
+ <th colspan="2" scope="col"></th>
47
+ </tr>
48
+ </thead>
49
+
50
+ <tbody>
51
+ <% resources.each do |resource| %>
52
+ <tr class="table__row"
53
+ role="link"
54
+ tabindex="0"
55
+ data-url="<%= polymorphic_path([namespace, resource]) -%>"
56
+ >
57
+ <% collection_presenter.attributes_for(resource).each do |attribute| %>
58
+ <td class="cell-data cell-data--<%= attribute.html_class %>">
59
+ <%= render_field attribute %>
60
+ </td>
61
+ <% end %>
62
+
63
+ <td><%= link_to(
64
+ t("administrate.actions.edit"),
65
+ [:edit, namespace, resource],
66
+ class: "action-edit",
67
+ ) %></td>
68
+
69
+ <td><%= link_to(
70
+ t("administrate.actions.destroy"),
71
+ [namespace, resource],
72
+ class: "table__action--destroy",
73
+ method: :delete,
74
+ data: { confirm: t("administrate.actions.confirm") }
75
+ ) %></td>
76
+ </tr>
77
+ <% end %>
78
+ </tbody>
79
+ </table>
@@ -0,0 +1,20 @@
1
+ <% @record.errors.each do |k, v| %>
2
+ var $errorOBJ_<%= k %> = $('#_form_id_<%= k %>');
3
+ var $errorFormGroup_<%= k %> = $errorOBJ_<%= k %>.parents('div.form-group');
4
+
5
+ $errorFormGroup_<%= k %>.removeClass('has-error');
6
+ $errorFormGroup_<%= k %>.find('p.help-block').remove();
7
+ $errorFormGroup_<%= k %>.addClass('has-error');
8
+ $errorOBJ_<%= k %>.after('<p class="help-block"><%= v %></p>');
9
+
10
+ $errorOBJ_<%= k %>.bind('keydown mousedown', function () {
11
+ $errorFormGroup_<%= k %>.removeClass('has-error');
12
+ $errorFormGroup_<%= k %>.find('p.help-block').remove();
13
+ });
14
+ <% end %>
15
+
16
+ <% if @record.errors.empty? %>
17
+ bootbox.alert("操作成功!", function(){
18
+ location.href = "<%= polymorphic_url [:admin, model] %>"
19
+ })
20
+ <% end %>
@@ -0,0 +1,62 @@
1
+ <div class="sidebar">
2
+ <ul>
3
+ <li>
4
+ <a href="/admin/dashboard">
5
+ <span class="glyphicon glyphicon-home"></span>
6
+ 首页</a>
7
+ </li>
8
+ </ul>
9
+ <section>
10
+ <div class="title">
11
+ 旅游团管理
12
+ </div>
13
+ <ul>
14
+ <li>
15
+ <a href="/admin/tour_groups/new">
16
+ <span class="glyphicon glyphicon-plus"></span>
17
+ 新增报备</a>
18
+ </li>
19
+ <li>
20
+ <a href="/admin/tour_groups">
21
+ <span class="glyphicon glyphicon-cog"></span>
22
+ 管理报备</a>
23
+ </li>
24
+ </ul>
25
+ </section>
26
+ <section>
27
+ <div class="title">
28
+ 执法管理
29
+ </div>
30
+ <ul>
31
+ <li>
32
+ <a href="/admin/users/new">
33
+ <span class="glyphicon glyphicon-plus"></span>
34
+ 新增用户</a>
35
+ </li>
36
+ <li>
37
+ <a href="/admin/users">
38
+ <span class="glyphicon glyphicon-cog"></span>
39
+ 管理用户</a>
40
+ </li>
41
+ <li>
42
+ <a href="/admin/contacts">
43
+ <span class="glyphicon glyphicon-phone"></span>
44
+ 联合执法</a>
45
+ </li>
46
+ </ul>
47
+ </section>
48
+ <section>
49
+ <div class="title">
50
+ 执法操作
51
+ </div>
52
+ <ul>
53
+ <li>
54
+ <a href="<%= home_index_path %>">
55
+ <span class="glyphicon glyphicon-list-alt"></span>
56
+ 开始执法
57
+ </a>
58
+ </li>
59
+ </ul>
60
+ </section>
61
+
62
+ </div>
@@ -0,0 +1,32 @@
1
+ <header class="topbanner">
2
+ <nav class="navbar navbar-default navbar-fixed-top" role="navigation" id="navigation" style="background-color: #ffffff;">
3
+ <div class="toggler">
4
+ <span class="glyphicon glyphicon-menu-hamburger"></span>
5
+ </div>
6
+ <div class="navbar-header">
7
+ <a href="/admin/dashboard" class="navbar-brand"></a>
8
+ <span class="org-name">欢迎使用sofa系统</span>
9
+ </div>
10
+
11
+ <div class="user-info">
12
+ <a id="user-avatar" href="#">
13
+ <%= image_tag (current_user.avatar_url and [current_user.avatar_url, '?x-oss-process=image/resize,m_fill,h_22,w_22'].join) || "default-avatar.png", class: "logo" %>
14
+ <span style="color: #32a9ff"><%= current_user.display_name %></span>
15
+ </a>
16
+ <div id="dropdown-menu">
17
+ <div class="arrow" style="left: 50%;"></div>
18
+ <ul>
19
+ <li>
20
+ <a href="<%= edit_admin_user_path(current_user) %>">修改密码</a>
21
+ </li>
22
+ <li>
23
+ <a href="/users/sign_out" data-method="delete">退出登录</a>
24
+ </li>
25
+ </ul>
26
+ </div>
27
+
28
+ </div>
29
+
30
+ </nav>
31
+
32
+ </header>
@@ -0,0 +1,3 @@
1
+ <%= link_to t('actions.recharge'),
2
+ 'javascript:;',
3
+ class: 'btn btn-primary btn-lg' %>
@@ -0,0 +1,5 @@
1
+ <%= link_to t('actions.destroy'),
2
+ [scope, record],
3
+ data: {confirm: t('confirm', action: t('actions.destroy')), method: 'delete', remote: true},
4
+ class: 'btn btn-sm btn-danger'
5
+ %>
@@ -0,0 +1 @@
1
+ <%= link_to t('actions.edit'), [scope, record, action: 'edit'], class: 'btn btn-primary btn-sm' %>
@@ -0,0 +1 @@
1
+ <%= link_to "[#{t('actions.edit_sights')}]", "#!/sights?filters[scenic_id]=#{record.id}"%>
@@ -0,0 +1,4 @@
1
+ <%= link_to t('actions.feedback'),
2
+ 'javascript:;',
3
+ class: 'btn btn-primary btn-lg',
4
+ data: {target: '#feedback', toggle: 'modal'} %>
@@ -0,0 +1 @@
1
+ <%= link_to "[#{t('actions.recharge')}]", [scope, record] %>
@@ -0,0 +1 @@
1
+ <%= link_to "[#{t('actions.destroy')}]", [scope, record], data: {confirm: t('confirm', action: t('actions.destroy')), method: 'delete', remote: true}%>
@@ -0,0 +1 @@
1
+ <%= link_to "[#{t('actions.edit')}]", [scope, record, action: 'edit']%>
@@ -0,0 +1 @@
1
+ <%= link_to "[#{t('actions.edit_sights')}]", "#!/sights?filters[scenic_id]=#{record.id}"%>
@@ -0,0 +1 @@
1
+ <%= link_to "[#{t('actions.show')}]", [scope, record] %>
@@ -0,0 +1 @@
1
+ <%= link_to [t('actions.new'), model.model_name.human].join, [scope, model, action: 'new'], class: 'btn btn-primary btn-sm' %>
@@ -0,0 +1 @@
1
+ <%= render 'save_js' %>
@@ -0,0 +1,6 @@
1
+ <% if @flag %>
2
+ alert("删除成功!")
3
+ location.reload();
4
+ <% else %>
5
+ alert("删除失败! <%= @record.errors.full_messages.join('\n') %>")
6
+ <% end %>
@@ -0,0 +1,18 @@
1
+ <div class="card">
2
+ <div class="title">
3
+ <span>
4
+ <%= decorate.try(:edit_page_title) || "编辑" %>
5
+ </span>
6
+ <div class="btn-groups" style="margin-left: auto;">
7
+ <%= yield(:permitted_methods).presence || render_class_actions(decorator) %>
8
+ </div>
9
+ </div>
10
+ <div class="body">
11
+ <%= yield(:breadcrumb_nav).presence || render('breadcrumb_nav') %>
12
+ <div class="show-box">
13
+ <%= form_for [:admin, record], builder: Admin::FormBuilder, enforce_utf8: false, html: {class: 'panel-form', novalidate: true, data: {remote: true}} do |f| %>
14
+ <%= f.build_form_for(decorator, :edit_form_attributes, :form_attributes) %>
15
+ <% end %>
16
+ </div>
17
+ </div>
18
+ </div>
@@ -0,0 +1,23 @@
1
+ <div class="card">
2
+ <div class="title">
3
+ <span>
4
+ <%= decorate.try(:index_page_title) || controller.controller_name_human %>
5
+ </span>
6
+ <div class="btn-groups" style="margin-left: auto;">
7
+ <%= yield(:permitted_methods).presence || render_class_actions(decorator) %>
8
+ </div>
9
+ </div>
10
+ <div class="body">
11
+ <%= yield(:breadcrumb_nav).presence || render('breadcrumb_nav') %>
12
+ <div class="filters-box clearfix">
13
+ <%= yield(:collection_filters).presence || collection_filters_tag(decorator, :collection_filters) %>
14
+ <%= yield(:collection_search).presence || collection_search_tag(decorator, :collection_search) %>
15
+ </div>
16
+ <div class="datalist">
17
+ <%= yield(:collection_table).presence || collection_table_tag(records, decorator, :collection_attributes) %>
18
+ <%= yield(:paginate).presence || paginate(records, theme: 'admin') %>
19
+ </div>
20
+ </section>
21
+
22
+ </div>
23
+ </div>
@@ -0,0 +1,18 @@
1
+ <div class="card">
2
+ <div class="title">
3
+ <span>
4
+ <%= decorate.try(:edit_page_title) || "新增" %>
5
+ </span>
6
+ <div class="btn-groups" style="margin-left: auto;">
7
+ <%= yield(:permitted_methods).presence || render_class_actions(decorator) %>
8
+ </div>
9
+ </div>
10
+ <div class="body">
11
+ <%= yield(:breadcrumb_nav).presence || render('breadcrumb_nav') %>
12
+ <div class="show-box">
13
+ <%= form_for record, url: [:admin, model], method: 'post', builder: Admin::FormBuilder, enforce_utf8: false, html: {class: 'panel-form', novalidate: true, data: {remote: true}} do |f| %>
14
+ <%= f.build_form_for(decorator, :form_attributes) %>
15
+ <% end %>
16
+ </div>
17
+ </div>
18
+ </div>
@@ -0,0 +1,101 @@
1
+ <div class="row thumbnail">
2
+ <div class="col-sm-4">
3
+ <input id="address-search-input" class="form-control" placeholder="输入关键字开始搜索" autocomplete='off'/>
4
+ </div>
5
+ <div class="col-sm-8">
6
+ <small id="map-address-result"></small>
7
+ </div>
8
+ <div class="" id="map-container" style="width: 100%;height: 300px;"></div>
9
+ </div>
10
+
11
+
12
+ <script type="text/javascript">
13
+ var latInputId = "<%= f.input_dom_id(options[:lat_field])%>";
14
+ var lngInputId = "<%= f.input_dom_id(options[:lng_field])%>";
15
+ require(['jq'], function () {
16
+ var $ = jQuery;
17
+
18
+ var markers = [];
19
+ $(function() {
20
+ var map = new AMap.Map("map-container", {
21
+ resizeEnable: true
22
+ });
23
+ var geocoder = new AMap.Geocoder({
24
+ radius: 1000,
25
+ extensions: "base"
26
+ });
27
+
28
+ var autoOptions = {
29
+ input: "address-search-input"
30
+ };
31
+ var auto = new AMap.Autocomplete(autoOptions);
32
+ AMap.event.addListener(auto, "select", selectItem);
33
+ function selectItem(e) {
34
+ updateLocationInputs(e.poi.location)
35
+ map.setCenter(e.poi.location);
36
+ map.setZoom(18);
37
+ addMarkerToMap(e.poi.location)
38
+ }
39
+
40
+ function addMarkerToMap(location) {
41
+ map.setCenter(location);
42
+ map.remove(markers);
43
+ var marker = new AMap.Marker({
44
+ position: location,
45
+ draggable: true,
46
+ cursor: 'move',
47
+ raiseOnDrag: true
48
+ });
49
+ marker.setMap(map);
50
+ AMap.event.addListener(marker, 'dragend', function(e){
51
+ updateLocationInputs(e.lnglat)
52
+ });
53
+
54
+ markers.push(marker);
55
+ }
56
+
57
+ // $('#cities').on('change', function(e){
58
+ // map.setCity($('#cities').val())
59
+ // auto.setCity($('#cities').val())
60
+ // })
61
+ // if($('#cities').val() ) {
62
+ // auto.setCity($('#cities').val())
63
+ // }
64
+
65
+ function updateLocationInputs(location) {
66
+ $('#' + latInputId).val(location.lat)
67
+ $('#' + lngInputId).val(location.lng)
68
+
69
+ geocoder.getAddress(location, function(status, result) {
70
+ if (status === 'complete' && result.info === 'OK') {
71
+ $('#map-address-result').html(result.regeocode.formattedAddress);
72
+ }
73
+ });
74
+
75
+ }
76
+
77
+ /*var placeSearch = new AMap.PlaceSearch({
78
+ map: map
79
+ });
80
+ AMap.event.addListener(auto, "select", select);
81
+ function select(e) {
82
+ placeSearch.setCity(e.poi.adcode);
83
+ placeSearch.search(e.poi.name);
84
+ }*/
85
+
86
+ map.plugin(["AMap.ToolBar"], function() {
87
+ map.addControl(new AMap.ToolBar());
88
+ });
89
+
90
+ function lnglatChanged() {
91
+ if($('#' + lngInputId).val() && $('#' + latInputId).val()) {
92
+ map.setZoomAndCenter(18, [$('#' + lngInputId).val(), $('#' + latInputId).val()])
93
+ addMarkerToMap([$('#' + lngInputId).val(), $('#' + latInputId).val()])
94
+ }
95
+ };
96
+
97
+ lnglatChanged();
98
+ });
99
+
100
+ });
101
+ </script>
@@ -0,0 +1,32 @@
1
+ <script type="text/javascript">
2
+ $(document).on('turbolinks:load', function(){
3
+ $('.sort-col').hide();
4
+ var saveSortingResult = function() {
5
+ var order_ids = $("<%= container_id%>").sortable("toArray", {attribute: 'data-id'});
6
+ $.ajax({
7
+ url: '/admin/<%= resource_parts %>/sort',
8
+ type: 'post',
9
+ contentType:'application/json',
10
+ data: JSON.stringify({ordered_ids: order_ids, current_page: $('#current_page').val(), per_page: $('#per_page').val() }),
11
+ dataType: 'application/json',
12
+ success: function(resp) {
13
+ alert("数据更新成功!");
14
+ }
15
+ })
16
+ }
17
+
18
+ $('<%= sort_btn_id%>').on('click', function(){
19
+ if ($('<%= sort_btn_id%>').hasClass('sorting')) {
20
+ $('<%= sort_btn_id%>').text('排序').removeClass('sorting');
21
+ $('.sort-col').hide();
22
+ $('<%= container_id%>').sortable({disabled: true}).enableSelection();
23
+ saveSortingResult();
24
+ } else {
25
+ alert("请拖拽每行数据开始排序!");
26
+ $('<%= sort_btn_id%>').text('完成').addClass('sorting');
27
+ $('.sort-col').show();
28
+ $('<%= container_id%>').sortable({disabled: false}).disableSelection();
29
+ }
30
+ })
31
+ });
32
+ </script>