sofav 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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>