rademade_admin 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/rademade_admin/app/common/location.coffee.erb +5 -1
  3. data/app/assets/javascripts/rademade_admin/app/common/status-toggler.coffee +25 -0
  4. data/app/assets/javascripts/rademade_admin/app/common/turboform.coffee +8 -0
  5. data/app/assets/javascripts/rademade_admin/app/form-popup/view.coffee +3 -3
  6. data/app/assets/javascripts/rademade_admin/app/gallery/image/collection-view.coffee +35 -0
  7. data/app/assets/javascripts/rademade_admin/app/gallery/image/collection.coffee +19 -0
  8. data/app/assets/javascripts/rademade_admin/app/gallery/image/model.coffee +25 -0
  9. data/app/assets/javascripts/rademade_admin/app/gallery/image/view.coffee +58 -0
  10. data/app/assets/javascripts/rademade_admin/app/gallery/view.coffee +40 -0
  11. data/app/assets/javascripts/rademade_admin/app/select2/related/view.coffee +1 -1
  12. data/app/assets/javascripts/rademade_admin/app/select2/view.coffee +11 -2
  13. data/app/assets/javascripts/rademade_admin/app/templates/crop.jst.ejs +2 -2
  14. data/app/assets/javascripts/rademade_admin/app/templates/related-item.jst.ejs +2 -2
  15. data/app/assets/javascripts/rademade_admin/form/form.coffee +4 -1
  16. data/app/assets/stylesheets/rademade_admin.sass.erb +2 -1
  17. data/app/assets/stylesheets/rademade_admin/blocks/form/input.sass +56 -27
  18. data/app/assets/stylesheets/rademade_admin/blocks/gallery/_main.sass +67 -0
  19. data/app/assets/stylesheets/rademade_admin/modules/pagination/main.sass +19 -2
  20. data/app/cells/menu/item.slim +2 -0
  21. data/app/cells/menu_cell.rb +8 -2
  22. data/app/controllers/rademade_admin/abstract_controller.rb +6 -2
  23. data/app/controllers/rademade_admin/dashboard_controller.rb +1 -1
  24. data/app/controllers/rademade_admin/file_controller.rb +14 -5
  25. data/app/controllers/rademade_admin/gallery_controller.rb +48 -0
  26. data/app/controllers/rademade_admin/model_controller.rb +37 -29
  27. data/app/controllers/rademade_admin/sessions_controller.rb +7 -6
  28. data/app/controllers/rademade_admin/status_controller.rb +16 -0
  29. data/app/helpers/rademade_admin/field_helper.rb +3 -4
  30. data/app/helpers/rademade_admin/form_helper.rb +35 -25
  31. data/app/helpers/rademade_admin/uri_helper.rb +6 -14
  32. data/app/inputs/rademade_admin/file_input.rb +24 -8
  33. data/app/inputs/rademade_admin/gallery_input.rb +77 -0
  34. data/app/inputs/rademade_admin/related_select_input.rb +13 -4
  35. data/app/serializers/autocomplete/base_serializer.rb +1 -1
  36. data/app/services/gallery/manager.rb +81 -0
  37. data/app/services/login.rb +3 -3
  38. data/app/services/menu_service.rb +1 -1
  39. data/app/services/menu_service/menu_item.rb +4 -0
  40. data/app/services/model_controller/model_options.rb +1 -0
  41. data/app/services/model_controller/notifier.rb +24 -10
  42. data/app/services/search/conditions/autocomplete.rb +4 -11
  43. data/app/services/search/conditions/list.rb +22 -10
  44. data/app/services/search/conditions/related_list.rb +8 -4
  45. data/app/services/search/where.rb +20 -0
  46. data/app/services/sortable_service.rb +1 -4
  47. data/app/services/status/toggler.rb +27 -0
  48. data/app/services/template_service.rb +33 -1
  49. data/app/services/upload/gallery_preview_service.rb +64 -0
  50. data/app/views/layouts/rademade_admin.html.erb +1 -22
  51. data/app/views/rademade_admin/_blocks/_form.html.erb +10 -0
  52. data/app/views/rademade_admin/_blocks/_header.html.erb +0 -12
  53. data/app/views/rademade_admin/_blocks/_search.html.erb +11 -0
  54. data/app/views/rademade_admin/_blocks/_sort_reset.html.erb +5 -0
  55. data/app/views/rademade_admin/_blocks/button/_cancel.html.erb +7 -0
  56. data/app/views/rademade_admin/_blocks/button/_destroy.html.erb +12 -0
  57. data/app/views/rademade_admin/_blocks/button/_edit.html.erb +4 -2
  58. data/app/views/rademade_admin/_blocks/button/_hide.html.erb +13 -0
  59. data/app/views/rademade_admin/_blocks/button/_preview.html.erb +3 -0
  60. data/app/views/rademade_admin/_blocks/form/_control.html.erb +9 -3
  61. data/app/views/rademade_admin/_blocks/form/_separator.html.erb +1 -0
  62. data/app/views/rademade_admin/_blocks/table/_head.html.erb +8 -2
  63. data/app/views/rademade_admin/_layouts/inner/index_table.html.erb +1 -3
  64. data/app/views/rademade_admin/_layouts/main.html.erb +26 -0
  65. data/app/views/rademade_admin/abstract/_form.html.erb +1 -7
  66. data/app/views/rademade_admin/abstract/index.html.erb +7 -13
  67. data/config/locales/rademade_admin.en.yml +16 -1
  68. data/config/locales/rademade_admin.ru.yml +22 -2
  69. data/config/routes.rb +9 -1
  70. data/lib/rademade_admin.rb +5 -0
  71. data/lib/rademade_admin/configuration.rb +6 -1
  72. data/lib/rademade_admin/engine.rb +4 -0
  73. data/lib/rademade_admin/gallery.rb +13 -0
  74. data/lib/rademade_admin/hideable.rb +37 -0
  75. data/lib/rademade_admin/input/related_select_input/related_list.rb +2 -2
  76. data/lib/rademade_admin/model/adapter/data.rb +8 -0
  77. data/lib/rademade_admin/model/adapter/data/active_record.rb +12 -2
  78. data/lib/rademade_admin/model/adapter/data/mongoid.rb +10 -8
  79. data/lib/rademade_admin/model/adapter/query/active_record.rb +8 -3
  80. data/lib/rademade_admin/model/configuration.rb +10 -8
  81. data/lib/rademade_admin/model/info.rb +13 -2
  82. data/lib/rademade_admin/model/info/data_item.rb +8 -3
  83. data/lib/rademade_admin/model/info/fields.rb +12 -2
  84. data/lib/rademade_admin/model/info/relation.rb +5 -0
  85. data/lib/rademade_admin/model/info/relation/gallery.rb +12 -0
  86. data/lib/rademade_admin/model/reflection.rb +4 -0
  87. data/lib/rademade_admin/routing/mapper.rb +1 -1
  88. data/lib/rademade_admin/routing/resource.rb +4 -0
  89. data/lib/rademade_admin/uploader/crop_photo.rb +3 -2
  90. data/lib/rademade_admin/version.rb +1 -1
  91. metadata +83 -8
@@ -0,0 +1,10 @@
1
+ <%
2
+ show_buttons = show_buttons.nil? ? true : show_buttons
3
+ buttons_template ||= @template_service.form_control_block
4
+ %><%= admin_form(@item, @model_class) do |f| %><%
5
+ @form_fields_without_locale.each do |form_field|
6
+ admin_field(f, form_field, @model_info)
7
+ end
8
+ concat render @template_service.form_lang_panel_block, { :f => f }
9
+ concat render buttons_template, { :f => f } if show_buttons
10
+ end %>
@@ -15,18 +15,6 @@
15
15
  <div class="menu-item">
16
16
  <span class="menu-link disabled"><%= @current_user %> <b class="caret"></b></span>
17
17
  </div>
18
- <div class="menu-item js-box hide">
19
- <span class="menu-link js-link"><i class="glyphicon glyphicon-list"></i></span>
20
- <div class="menu-droplist js-droplist">
21
- <%# <div class="menu-droplist-header">Active links</div>
22
- <a class="menu-droplist-link" href="#">Link</a>
23
- <a class="menu-droplist-link" href="#">Link</a>
24
- <div class="menu-droplist-header">Disable links</div>
25
- <span class="menu-droplist-link disabled">Disable link</span>
26
- <span class="menu-droplist-link disabled">Disable link</span> %>
27
- <%= link_to t('rademade_admin.exit'), [:logout, :sessions], { :method => :delete, :class => 'menu-droplist-link last' } %>
28
- </div>
29
- </div>
30
18
  <div class="menu-item">
31
19
  <%= link_to t('rademade_admin.exit'), [:logout, :sessions], { :method => :delete, :class => 'menu-link last' } %>
32
20
  </div>
@@ -0,0 +1,11 @@
1
+ <%
2
+ unless @model_info.data_items.filter_fields.empty?
3
+ list_uri = admin_list_uri(@model)
4
+ %><form class="form-box search" action="<%= list_uri %>" data-turboform>
5
+ <div class="input-holder">
6
+ <input type="text" name="q" value="<%= params[:q] %>"/>
7
+ </div>
8
+ <button class="btn blue-btn"><%= t('rademade_admin.search') %></button>
9
+ <a class="btn yellow-btn" href="<%= list_uri %>"><%= t('rademade_admin.clear_search') %></a>
10
+ </form><%
11
+ end %>
@@ -0,0 +1,5 @@
1
+ <%
2
+ if @sortable_service.can_reset?
3
+ %><a href="<%= admin_url_for(request.path_parameters, true) %>"><%= t('rademade_admin.reset_sort') %></a><%
4
+ end
5
+ %>
@@ -0,0 +1,7 @@
1
+ <%
2
+ if breadcrumbs && breadcrumbs.items.length > 2
3
+ back_url = breadcrumbs.items[-2][1]
4
+ else
5
+ back_url = admin_list_uri(@model)
6
+ end
7
+ concat link_to t('rademade_admin.cancel'), back_url || '', :class => 'cancel-btn' %>
@@ -0,0 +1,12 @@
1
+ <%
2
+ if can? :destroy, @model
3
+ delete_uri = admin_delete_uri(item)
4
+ unless delete_uri.nil?
5
+ %><div class="glyphicon glyphicon-remove fl-l"><%
6
+ concat button_to t('rademade_admin.destroy'), delete_uri, {
7
+ :method => :delete,
8
+ :form => { :class => 'delete-item-form' }
9
+ }
10
+ %></div><%
11
+ end
12
+ end %>
@@ -1,3 +1,5 @@
1
1
  <%
2
- edit_url = admin_edit_uri(item)
3
- concat link_to t('rademade_admin.edit'), edit_url, :class => 'glyphicon glyphicon-pencil fl-l' if edit_url %>
2
+ if can? :edit, @model
3
+ edit_url = admin_edit_uri(item)
4
+ concat link_to t('rademade_admin.edit'), edit_url, :class => 'glyphicon glyphicon-pencil fl-l' unless edit_url.nil?
5
+ end %>
@@ -0,0 +1,13 @@
1
+ <%
2
+ if @model_info.hideable? && can?(:edit, @model)
3
+ element_id = "hide_#{item.id}"
4
+ toggle_url = admin_url_for(:controller => :status, :action => :toggle, :model => @model, :id => item.id)
5
+ %><div class="view-option">
6
+ <input id="<%=element_id%>" data-toggle-url="<%= toggle_url %>" type="checkbox"<%
7
+ if item.shown?
8
+ %> checked="checked"<%
9
+ end
10
+ %>/>
11
+ <label for="<%=element_id %>" class="glyphicon"></label>
12
+ </div><%
13
+ end %>
@@ -0,0 +1,3 @@
1
+ <%
2
+ preview_url = @model_info.preview_url(item)
3
+ concat link_to '', preview_url, :class => 'glyphicon glyphicon-new-window', :target => :blank unless preview_url.nil? %>
@@ -1,3 +1,9 @@
1
- <%= f.button :submit, :class => 'blue-btn' %>
2
- <span class="btn-sep"><%= t('rademade_admin.or') %></span>
3
- <%= link_to t('rademade_admin.cancel'), admin_list_uri(@model) || '', :class => 'cancel-btn' %>
1
+ <%= f.button :submit, :class => 'blue-btn' %><%
2
+ if @with_create_and_return_button
3
+ concat render @template_service.form_separator_block
4
+ translate_name = f.object.new_record? ? 'helpers.submit.create' : 'helpers.submit.update'
5
+ submit_button_text = "#{t(translate_name, :model => f.object.class)} #{t('rademade_admin.return')}"
6
+ concat f.submit submit_button_text, :class => "#{SimpleForm.button_class} blue-btn", :name => 'create_and_return'
7
+ end
8
+ concat render @template_service.form_separator_block
9
+ concat render @template_service.cancel_button %>
@@ -0,0 +1 @@
1
+ <span class="btn-sep"><%= t('rademade_admin.or') %></span>
@@ -1,8 +1,14 @@
1
1
  <thead class="table-header">
2
2
  <tr class="table-line"><%
3
3
  list_fields.each do |field|
4
- %><th class="table-item" data-column="<%= field.name %>">
5
- <span><%= field.label + @sortable_service.sorting_sign(field) %></span>
4
+ sorting_sign = ''
5
+ %><th class="table-item"<%
6
+ unless field.order_column.nil?
7
+ sorting_sign = @sortable_service.sorting_sign(field)
8
+ %> data-column="<%= field.order_column %>"<%
9
+ end
10
+ %>>
11
+ <span><%= field.label + sorting_sign %></span>
6
12
  </th><%
7
13
  end
8
14
  %><th class="table-item">
@@ -1,8 +1,6 @@
1
1
  <% content_for :content do %><%
2
2
  concat render @template_service.on_page_select_block
3
- if @sortable_service.can_reset?
4
- %><a href="<%= request.path %>"><%= t('rademade_admin.reset_sort') %></a><%
5
- end
3
+ concat render @template_service.sort_reset_block
6
4
  %><table class="table-box"><%
7
5
  concat render @template_service.table_head_block, {
8
6
  :list_fields => @list_fields
@@ -0,0 +1,26 @@
1
+ <% content_for :head do %>
2
+ <%= stylesheet_link_tag(:rademade_admin, :media => 'all', 'data-turbolinks-track' => true) %>
3
+ <%= javascript_include_tag(:rademade_admin, 'data-turbolinks-track' => true) %>
4
+ <% end %>
5
+
6
+ <!DOCTYPE html>
7
+ <html>
8
+ <head>
9
+ <title>Rademade Admin</title>
10
+ <%= yield(:head) %>
11
+ <%= csrf_meta_tags %>
12
+ </head>
13
+
14
+ <body>
15
+ <div class="wrapper">
16
+ <%= yield %>
17
+ </div>
18
+ </body>
19
+
20
+ <%= javascript_tag do %>
21
+ I18n.defaultLocale = "<%= I18n.default_locale %>";
22
+ I18n.locale = "<%= I18n.locale %>";
23
+ I18n.fallbacks = true;
24
+ <% end %>
25
+
26
+ </html>
@@ -1,7 +1 @@
1
- <%= admin_form(@item, @model_class) do |f| %><%
2
- @form_fields_without_locale.each do |form_field|
3
- admin_field(f, form_field, @model_info)
4
- end
5
- concat render @template_service.form_lang_panel, { :f => f }
6
- concat render @template_service.form_control_block, { :f => f }
7
- end %>
1
+ <%= render @template_service.form_block %>
@@ -11,9 +11,8 @@ end %>
11
11
 
12
12
  <% content_for :content do %><%
13
13
  concat render @template_service.on_page_select_block
14
- if @sortable_service.can_reset?
15
- %><a href="<%= request.path %>"><%= t('rademade_admin.reset_sort') %></a><%
16
- end
14
+ concat render @template_service.search_block
15
+ concat render @template_service.sort_reset_block
17
16
  %><table class="table-box"><%
18
17
  concat render @template_service.table_head_block, {
19
18
  :list_fields => @list_fields
@@ -31,16 +30,11 @@ end %>
31
30
  end
32
31
  %><td class="table-item">
33
32
  <span class="table-actions"><%
34
- concat render 'rademade_admin/_blocks/button/edit', {
35
- :item => item
36
- }
37
- %><div class="glyphicon glyphicon-remove fl-l"><%
38
- concat button_to t('rademade_admin.destroy'), admin_delete_uri(item), {
39
- :method => :delete,
40
- :form => { :class => 'delete-item-form' }
41
- }
42
- %></div>
43
- </span>
33
+ concat render 'rademade_admin/_blocks/button/edit', { :item => item }
34
+ concat render 'rademade_admin/_blocks/button/hide', { :item => item }
35
+ concat render 'rademade_admin/_blocks/button/preview', { :item => item }
36
+ concat render 'rademade_admin/_blocks/button/destroy', { :item => item }
37
+ %></span>
44
38
  </td>
45
39
  </tr><%
46
40
  end
@@ -23,11 +23,26 @@ en:
23
23
  search: "Search"
24
24
  edit_record: "Edit"
25
25
  upload_file: "Upload file"
26
+ download_file: "Download file"
26
27
  enter_search: "Enter search phrase"
27
28
  record_remove_confirm: "Do you really want delete this record?"
28
29
  model_remove_confirm: "Do you really want delete this model?"
30
+ image_remove_confirm: "Do you really want delete this image?"
29
31
  language: "Language"
30
32
  locale_en: "English"
31
33
  locale_ru: "Russian"
32
34
  edit_related_item: "Edit"
33
- crop: "Crop"
35
+ crop: "Crop"
36
+ discard: "Discard"
37
+ return: "and return"
38
+ login_email_not_found: "There is no users with such email"
39
+ login_incorrect_password: "Incorrect password"
40
+ login_access_denied: "Access denied"
41
+ success_message: "Ok"
42
+ success_insert_message: "Entity was inserted!"
43
+ success_update_message: "Entity data was updated!"
44
+ success_delete_message: "Entity was deleted!"
45
+ success_unlink_message: "Entity was unlinked!"
46
+ success_link_message: "Entity was linked!"
47
+ success_status_update_message: "Status was updated!"
48
+ clear_search: "Clear"
@@ -23,6 +23,26 @@ ru:
23
23
  search: "Поиск"
24
24
  edit_record: "Редактировать"
25
25
  upload_file: "Загрузить файл"
26
+ download_file: "Скачать файл"
26
27
  enter_search: "Введите фразу для поиска"
27
- record_remove_confirm: "Вы действительно хотите удалть данную запись?"
28
- model_remove_confirm: "Вы действительно хотите удалить данную модель?"
28
+ record_remove_confirm: "Вы действительно хотите удалить данную запись?"
29
+ model_remove_confirm: "Вы действительно хотите удалить данную модель?"
30
+ image_remove_confirm: "Вы действительно хотите удалить данную картинку?"
31
+ language: "Язык"
32
+ locale_en: "Английский"
33
+ locale_ru: "Русский"
34
+ edit_related_item: "Редактировать"
35
+ crop: "Обрезать"
36
+ discard: "Отменить"
37
+ return: "и вернуться"
38
+ login_email_not_found: "Пользователь не найден"
39
+ login_incorrect_password: "Неверный пароль"
40
+ login_access_denied: "Отказано в доступе"
41
+ success_message: "Ok"
42
+ success_insert_message: "Запись вставлена!"
43
+ success_update_message: "Запись обновлена!"
44
+ success_delete_message: "Запись удалена!"
45
+ success_unlink_message: "Запись отсоединена!"
46
+ success_link_message: "Запись соединена!"
47
+ success_status_update_message: "Статус обновлен!"
48
+ clear_search: "Очистить"
data/config/routes.rb CHANGED
@@ -6,10 +6,18 @@ RademadeAdmin::Engine.routes.draw do
6
6
  root 'dashboard#index'
7
7
 
8
8
  match 'file-upload' => 'file#upload', :via => [:post, :patch]
9
+ match 'file-download/:model/:id/:uploader/:column' => 'file#download', :via => [:get]
9
10
  match 'file-crop' => 'file#crop', :via => [:post, :patch]
10
11
 
12
+ match 'gallery-upload' => 'gallery#upload', :via => [:post, :patch]
13
+ match 'gallery-crop' => 'gallery#crop', :via => [:post, :patch]
14
+ match 'gallery-sort' => 'gallery#sort', :via => [:post, :patch]
15
+ match 'gallery-remove/:id' => 'gallery#remove', :via => [:delete]
16
+
17
+ match 'status/:model/:id' => 'status#toggle', :via => [:post, :patch]
18
+
11
19
  post 'sessions' => 'sessions#login'
12
- get 'login' => 'dashboard#login', :as => 'login'
20
+ get 'login' => 'dashboard#login', :as => :login
13
21
 
14
22
  resources :sessions do
15
23
  get 'logout', :on => :collection
@@ -6,6 +6,7 @@ require 'carrierwave'
6
6
  require 'cancan'
7
7
  require 'bower-rails'
8
8
  require 'compass-rails'
9
+ require 'select2-rails'
9
10
 
10
11
  # js assets
11
12
  require 'turbolinks'
@@ -28,4 +29,8 @@ module RademadeAdmin
28
29
  RademadeAdmin::Configuration.user_class
29
30
  end
30
31
 
32
+ def self.ability_class
33
+ RademadeAdmin::Configuration.ability_class
34
+ end
35
+
31
36
  end
@@ -2,7 +2,7 @@
2
2
  module RademadeAdmin
3
3
  class Configuration
4
4
  class << self
5
- attr_reader :user_class
5
+ attr_reader :user_class, :ability_class
6
6
 
7
7
  def configure(&block)
8
8
  instance_eval &block
@@ -13,6 +13,11 @@ module RademadeAdmin
13
13
  def admin_model(model)
14
14
  @user_class ||= model
15
15
  end
16
+
17
+ def ability_model(model)
18
+ @ability_class ||= model
19
+ end
20
+
16
21
  end
17
22
  end
18
23
  end
@@ -9,6 +9,10 @@ module RademadeAdmin
9
9
 
10
10
  config.assets.paths << "#{config.root}/vendor/assets/javascript/bower_components"
11
11
 
12
+ initializer 'ckeditor.assets_precompile', :group => :all do |app|
13
+ app.config.assets.precompile += %w( rademade_admin.css rademade_admin.js ckeditor/* )
14
+ end
15
+
12
16
  $LOAD_PATH << "#{config.root}/app/services/"
13
17
 
14
18
  paths = %W(
@@ -0,0 +1,13 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module RademadeAdmin
3
+ module Gallery
4
+
5
+ def method_missing(name, *arguments)
6
+ if name == 'images'
7
+ raise NotImplementedError.new 'Implement "images" method'
8
+ end
9
+ super
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,37 @@
1
+ module RademadeAdmin
2
+ module Hideable
3
+
4
+ STATUS_HIDDEN = 0
5
+ STATUS_SHOWN = 1
6
+
7
+ def method_missing(name, *arguments)
8
+ if %w(status status=).include? name
9
+ raise NotImplementedError.new "Implement '#{name}' method"
10
+ end
11
+ super
12
+ end
13
+
14
+ def shown?
15
+ item_status = send(:status)
16
+ if item_status.is_a? Fixnum
17
+ item_status == STATUS_SHOWN
18
+ else
19
+ # for boolean values
20
+ item_status
21
+ end
22
+ end
23
+
24
+ def show
25
+ send(:status=, STATUS_SHOWN)
26
+ end
27
+
28
+ def hide
29
+ send(:status=, STATUS_HIDDEN)
30
+ end
31
+
32
+ def toggle
33
+ shown? ? hide : show
34
+ end
35
+
36
+ end
37
+ end
@@ -36,10 +36,10 @@ module RademadeAdmin
36
36
  end
37
37
 
38
38
  def related_list_item_edit_html(serialized_value)
39
- if serialized_value[:edit_url]
39
+ if serialized_value[:editurl]
40
40
  template.content_tag(
41
41
  :button, I18n.t('rademade_admin.edit_related_item'),
42
- :'data-edit' => serialized_value[:edit_url]
42
+ :'data-edit' => serialized_value[:editurl]
43
43
  )
44
44
  else
45
45
  ''
@@ -53,6 +53,10 @@ module RademadeAdmin
53
53
  @fields ||= _map_fields
54
54
  end
55
55
 
56
+ def columns
57
+ @columns ||= _model_fields
58
+ end
59
+
56
60
  #
57
61
  # @return [RademadeAdmin::Model::Info::Field]
58
62
  #
@@ -113,6 +117,10 @@ module RademadeAdmin
113
117
  @model.uploaders
114
118
  end
115
119
 
120
+ def _model_fields
121
+ fields.keys
122
+ end
123
+
116
124
  end
117
125
  end
118
126
  end