social_stream 2.2.1 → 2.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +1 -1
  3. data/base/app/assets/javascripts/social_stream/comment.js +1 -1
  4. data/base/app/assets/javascripts/social_stream/search_header.js +26 -4
  5. data/base/app/assets/stylesheets/social_stream/base/contacts/layouts/_contacts.css.sass +1 -0
  6. data/base/app/assets/stylesheets/social_stream/base/footer/layout/_footer.css.sass +1 -1
  7. data/base/app/assets/stylesheets/social_stream/base/frontpage_devise/_devise.css.sass +5 -3
  8. data/base/app/assets/stylesheets/social_stream/base/frontpage_devise/layout/_devise.css.sass +7 -37
  9. data/base/app/assets/stylesheets/social_stream/base/frontpage_devise/layout/_frontpage.css.sass +4 -2
  10. data/base/app/assets/stylesheets/social_stream/base/frontpage_devise/responsive/_responsive-1200px-min.css.sass +6 -3
  11. data/base/app/assets/stylesheets/social_stream/base/frontpage_devise/responsive/_responsive-767px-max.css.sass +9 -5
  12. data/base/app/assets/stylesheets/social_stream/base/frontpage_devise/responsive/_responsive-768px-979px.css.sass +3 -4
  13. data/base/app/assets/stylesheets/social_stream/base/layouts/_header.css.sass +3 -2
  14. data/base/app/assets/stylesheets/social_stream/base/mixins/_buttons.css.sass +1 -2
  15. data/base/app/controllers/groups_controller.rb +4 -0
  16. data/base/app/controllers/home_controller.rb +15 -0
  17. data/base/app/controllers/search_controller.rb +3 -3
  18. data/base/app/decorators/avatars_controller_decorator.rb +1 -0
  19. data/base/app/overrides/avatars/_crop/add_actor_id.rb +4 -0
  20. data/base/app/overrides/avatars/_form/add_actor_id.rb +4 -0
  21. data/base/app/views/contacts/_new_modal.html.erb +2 -2
  22. data/base/app/views/devise/confirmations/new.html.erb +14 -9
  23. data/base/app/views/devise/passwords/edit.html.erb +23 -26
  24. data/base/app/views/devise/passwords/new.html.erb +7 -3
  25. data/base/app/views/devise/registrations/_edit_user.html.erb +1 -1
  26. data/base/app/views/devise/registrations/new.html.erb +4 -8
  27. data/base/app/views/devise/shared/_links.erb +1 -3
  28. data/base/app/views/groups/_form.html.erb +2 -1
  29. data/base/app/views/layouts/_header_dropdown_menu_sessions.html.erb +1 -1
  30. data/base/app/views/layouts/_header_signed_in.erb +22 -26
  31. data/base/app/views/profiles/_personal_edit.html.erb +2 -2
  32. data/base/config/locales/de.yml +7 -0
  33. data/base/config/locales/devise.de.yml +61 -0
  34. data/base/config/locales/devise.fr.yml +61 -0
  35. data/base/config/locales/devise.hu.yml +60 -0
  36. data/base/config/locales/devise.nl.yml +60 -0
  37. data/base/config/locales/en.yml +5 -1
  38. data/base/config/locales/es.yml +8 -1
  39. data/base/config/locales/fr.yml +7 -0
  40. data/base/config/locales/hu.yml +22 -15
  41. data/base/config/locales/nl.yml +7 -0
  42. data/base/config/locales/pt.yml +7 -0
  43. data/base/config/locales/zh.yml +7 -0
  44. data/base/lib/social_stream/base/autoload.rb +1 -0
  45. data/base/lib/social_stream/base/version.rb +1 -1
  46. data/base/lib/social_stream/controllers/authorship.rb +2 -1
  47. data/base/lib/social_stream/controllers/avatars.rb +14 -0
  48. data/base/lib/social_stream/controllers/helpers.rb +3 -3
  49. data/base/lib/social_stream/controllers/objects.rb +6 -7
  50. data/base/lib/tasks/i18n.rake +148 -0
  51. data/base/social_stream-base.gemspec +2 -1
  52. data/config/locales/en.yml +2 -1
  53. data/config/locales/es.yml +2 -1
  54. data/documents/app/controllers/documents_controller.rb +26 -16
  55. data/documents/app/models/document.rb +4 -3
  56. data/documents/app/models/video.rb +11 -9
  57. data/documents/app/views/audios/_audio_show.html.erb +1 -1
  58. data/documents/app/views/videos/_video_show.html.erb +1 -1
  59. data/documents/lib/social_stream/documents/version.rb +1 -1
  60. data/documents/social_stream-documents.gemspec +2 -1
  61. data/events/lib/social_stream/events/version.rb +1 -1
  62. data/events/social_stream-events.gemspec +2 -1
  63. data/lib/social_stream/version.rb +1 -1
  64. data/linkser/lib/social_stream/linkser/version.rb +1 -1
  65. data/linkser/social_stream-linkser.gemspec +2 -1
  66. data/oauth2_server/app/models/site/client.rb +16 -0
  67. data/oauth2_server/app/views/site/clients/_edit.html.erb +6 -0
  68. data/oauth2_server/app/views/site/clients/_edit_step_2.html.erb +1 -1
  69. data/oauth2_server/app/views/site/clients/_edit_step_3.html.erb +1 -2
  70. data/oauth2_server/app/views/site/clients/_form.html.erb +1 -1
  71. data/oauth2_server/config/locales/en.yml +1 -1
  72. data/oauth2_server/config/locales/es.yml +2 -1
  73. data/oauth2_server/config/locales/zh.yml +1 -0
  74. data/oauth2_server/lib/social_stream/oauth2_server/version.rb +1 -1
  75. data/oauth2_server/social_stream-oauth2_server.gemspec +2 -1
  76. data/ostatus/app/controllers/remote_subjects_controller.rb +1 -1
  77. data/ostatus/lib/social_stream/ostatus/version.rb +1 -1
  78. data/ostatus/social_stream-ostatus.gemspec +2 -1
  79. data/places/social_stream-places.gemspec +1 -0
  80. data/presence/lib/social_stream/presence/version.rb +1 -1
  81. data/presence/social_stream-presence.gemspec +2 -1
  82. data/social_stream.gemspec +7 -7
  83. metadata +25 -18
  84. data/base/app/views/home/index.js.erb +0 -5
  85. data/lib/tasks/i18n.rake +0 -75
@@ -20,6 +20,7 @@ en:
20
20
  change: Change password
21
21
  new: New password
22
22
  retype: Retype new password
23
+ current: Current password
23
24
  activerecord:
24
25
  attributes:
25
26
  contact:
@@ -191,6 +192,9 @@ en:
191
192
  title: Add %{name} to your contacts
192
193
  menu: Add contact
193
194
  submit: Add Contact
195
+ new_modal:
196
+ label:
197
+ relations: Initially assigned roles
194
198
  one: Contact
195
199
  other: Contacts
196
200
  pending:
@@ -594,7 +598,7 @@ en:
594
598
  name: API Key
595
599
  regenerate: Regenerate API key
596
600
  cancel_account:
597
- briefing: Lets you cancel your account
601
+ briefing: Cancel account
598
602
  email_change:
599
603
  briefing: Change your email
600
604
  lang_change:
@@ -11,6 +11,7 @@ es:
11
11
  one: Cuenta
12
12
  password:
13
13
  change: Cambiar contraseña
14
+ current: Contraseña actual
14
15
  new: Nueva contraseña
15
16
  retype: Repetir nueva contraseña
16
17
  action:
@@ -185,9 +186,15 @@ es:
185
186
  menu: Añadir contacto
186
187
  modal:
187
188
  button: Añadir
189
+ placeholder:
190
+ actors: Type names
191
+ relations: Type names
188
192
  title: Añadir contactos
189
193
  submit: Añadir
190
194
  title: Añadir a %{name} como contacto
195
+ new_modal:
196
+ label:
197
+ relations: Initially assigned roles
191
198
  one: Contacto
192
199
  other: Contactos
193
200
  pending:
@@ -600,7 +607,7 @@ es:
600
607
  name: Clave API
601
608
  regenerate: Regenerar clave API
602
609
  cancel_account:
603
- briefing: Te permite cancelar tu cuenta
610
+ briefing: Cancelar cuenta
604
611
  email_change:
605
612
  briefing: Cambia tu email
606
613
  error: Hubo errores al guardar los cambios
@@ -11,6 +11,7 @@ fr:
11
11
  one: Compte
12
12
  password:
13
13
  change: Modifier le mot de passe
14
+ current: Current password
14
15
  new: Nouveau mot de passe
15
16
  retype: Confirmer le nouveau mot de passe
16
17
  action:
@@ -185,9 +186,15 @@ fr:
185
186
  menu: Ajouter le contact
186
187
  modal:
187
188
  button: Add
189
+ placeholder:
190
+ actors: Type names
191
+ relations: Type names
188
192
  title: Add contacts
189
193
  submit: Ajouter le contact
190
194
  title: Ajouter %{name} à vos contacts
195
+ new_modal:
196
+ label:
197
+ relations: Initially assigned roles
191
198
  one: Contact
192
199
  other: Contacts
193
200
  pending:
@@ -11,10 +11,11 @@ hu:
11
11
  one: Fiók
12
12
  password:
13
13
  change: Jelszó megváltoztatása
14
+ current: Current password
14
15
  new: Új jelszó
15
16
  retype: Jelszó újra
16
17
  action:
17
- accept: Elfogad
18
+ accept: Elfogadás
18
19
  send: Elküld
19
20
  activerecord:
20
21
  attributes:
@@ -40,7 +41,7 @@ hu:
40
41
  summary: Nyilvános
41
42
  show: Bemutatás
42
43
  visible:
43
- full: ' Megosztva az %{audience}-szel'
44
+ full: ' Megosztva az %{audience}-el'
44
45
  summary: Korlátozott
45
46
  confirm_delete: Törlöd a tevékenységet?
46
47
  delete: Törlés
@@ -80,10 +81,10 @@ hu:
80
81
  follow:
81
82
  Group:
82
83
  message: '%{name} hozzáadott téged a kapcsolataihoz.'
83
- title: '%{subject}-t hozzáadta %{contact}-t, mint kapcsolatot.'
84
+ title: '%{subject} hozzáadta %{contact}-t, mint kapcsolatot.'
84
85
  User:
85
86
  message: '%{name} hozzáadott téged a kapcsolataihoz.'
86
- title: '%{subject}-t hozzáadta %{contact}-t, mint kapcsolatot.'
87
+ title: '%{subject} hozzáadta %{contact}-t, mint kapcsolatot.'
87
88
  join:
88
89
  one: '%{sender} csatlakozott a %{title} %{thing}-hoz.'
89
90
  like:
@@ -96,7 +97,7 @@ hu:
96
97
  make-friend:
97
98
  Group:
98
99
  message: '%{name} hozzáadott téged a kapcsolataihoz.'
99
- title: '%{subject}-t hozzáadta %{contact}-t, mint kapcsolatot.'
100
+ title: '%{subject} hozzáadta %{contact}-t, mint kapcsolatot.'
100
101
  User:
101
102
  message: '%{name} hozzáadott téged a kapcsolataihoz.'
102
103
  title: '%{subject} és %{contact} mostantól kapcsolatban állnak egymással.'
@@ -112,7 +113,7 @@ hu:
112
113
  more:
113
114
  one: '%{count}-vel több személy'
114
115
  other: '%{count}–vel több személy'
115
- unfollow: Nemkövetés
116
+ unfollow: Követés megszüntetése
116
117
  actor:
117
118
  name: Név
118
119
  title:
@@ -163,7 +164,7 @@ hu:
163
164
  one: Egy hiba akadályozza a névjegy mentését
164
165
  other: '%{count} hiba akadályozza a névjegy mentését'
165
166
  follow: Kövesd
166
- following: Követés
167
+ following: Követett
167
168
  graph:
168
169
  empty: Sajnos jelenleg még nincsenek névjegyeid. Próbáld meg a keresőt használni!
169
170
  one: Gráf
@@ -184,9 +185,15 @@ hu:
184
185
  menu: Kapcsolat hozzáadása
185
186
  modal:
186
187
  button: Add
188
+ placeholder:
189
+ actors: Type names
190
+ relations: Type names
187
191
  title: Add contacts
188
192
  submit: Kapcsolat hozzáadása
189
193
  title: '%{name} hozzáadása kapcsolataidhoz'
194
+ new_modal:
195
+ label:
196
+ relations: Initially assigned roles
190
197
  one: Kapcsolat
191
198
  other: Kapcsolatok
192
199
  pending:
@@ -209,7 +216,7 @@ hu:
209
216
  other: Javaslatok
210
217
  type:
211
218
  new: + Új típus
212
- unfollow: Nemkövetett
219
+ unfollow: Követés megszüntetése
213
220
  view_all: View all...
214
221
  copyright: 2010 Copyright – Minden jog fenntartva
215
222
  counter:
@@ -360,7 +367,7 @@ hu:
360
367
  toolbar: Meghívó
361
368
  lang:
362
369
  browser: Automatikusan felismert böngésző nyelv
363
- none: Nyelv-független tartalom
370
+ none: Nyelv független tartalom
364
371
  layout:
365
372
  more: See more (%{count})
366
373
  like:
@@ -375,7 +382,7 @@ hu:
375
382
  delete: Törlés
376
383
  delete_confirm: A lomtárba akarod tenni a '%{object}'-t?
377
384
  form:
378
- body: Üzenettörzs
385
+ body: Üzenet
379
386
  recipients: Címzettek
380
387
  subject: Tárgy
381
388
  mark_as_read: Jelezd olvasottként
@@ -452,7 +459,7 @@ hu:
452
459
  default:
453
460
  brief:
454
461
  create:
455
- activity: Posztolj az üzenőfaladra
462
+ activity: Írj az üzenőfaladra
456
463
  follow:
457
464
  nil: Kövesd a tevékenységüket
458
465
  notify:
@@ -510,11 +517,11 @@ hu:
510
517
  profile:
511
518
  actualcity: Jelenlegi lakhely
512
519
  address: Cím
513
- age: Kor
520
+ age: Korosztály
514
521
  contact: Elérhetőség
515
522
  country: Ország
516
523
  email: Email
517
- empty: Ezek a mezők üresek. Légy szíves frissítsd ezeket.
524
+ empty: Ezek a mezők üresek. Légy szíves frissítsd!
518
525
  fax: Fax
519
526
  group:
520
527
  about: Rólunk
@@ -541,7 +548,7 @@ hu:
541
548
  experience: Szakmai tapasztalat
542
549
  info: Személyes információk
543
550
  tags: Felhasználói címkék
544
- website: Website
551
+ website: Weboldal
545
552
  public:
546
553
  other: Mindenki
547
554
  relation_custom:
@@ -639,7 +646,7 @@ hu:
639
646
  this_is_you: Ez te vagy!
640
647
  sure: Biztos vagy benne?
641
648
  time:
642
- ago: '%{time}-vel ezelőtt '
649
+ ago: '%{time}ja'
643
650
  unknown: Ismeretlen
644
651
  user:
645
652
  all: Az összes felhasználó
@@ -11,6 +11,7 @@ nl:
11
11
  one: Account
12
12
  password:
13
13
  change: Wachtwoord wijzigen
14
+ current: Current password
14
15
  new: Nieuw wachtwoord
15
16
  retype: Typ nieuw wachtwoord nogmaals
16
17
  action:
@@ -185,9 +186,15 @@ nl:
185
186
  menu: Contact toevoegen
186
187
  modal:
187
188
  button: Add
189
+ placeholder:
190
+ actors: Type names
191
+ relations: Type names
188
192
  title: Add contacts
189
193
  submit: Contact toevoegen
190
194
  title: '%{name} toevoegen aan uw contacten'
195
+ new_modal:
196
+ label:
197
+ relations: Initially assigned roles
191
198
  one: Contact
192
199
  other: Contacten
193
200
  pending:
@@ -11,6 +11,7 @@ pt:
11
11
  one: Conta
12
12
  password:
13
13
  change: Mudar senha
14
+ current: Current password
14
15
  new: Nova senha
15
16
  retype: Repetir nova senha
16
17
  action:
@@ -185,9 +186,15 @@ pt:
185
186
  menu: Adicionar contato
186
187
  modal:
187
188
  button: Add
189
+ placeholder:
190
+ actors: Type names
191
+ relations: Type names
188
192
  title: Add contacts
189
193
  submit: Adicionar
190
194
  title: Adicionar %{name} aos seus contatos
195
+ new_modal:
196
+ label:
197
+ relations: Initially assigned roles
191
198
  one: Contato
192
199
  other: Contatos
193
200
  pending:
@@ -11,6 +11,7 @@ zh:
11
11
  one: 帐号
12
12
  password:
13
13
  change: 修改密码
14
+ current: Current password
14
15
  new: 新密码
15
16
  retype: 再次输入新密码
16
17
  action:
@@ -184,9 +185,15 @@ zh:
184
185
  menu: 加入联络
185
186
  modal:
186
187
  button: Add
188
+ placeholder:
189
+ actors: Type names
190
+ relations: Type names
187
191
  title: Add contacts
188
192
  submit: 加入联络
189
193
  title: 加入 %{name} 到您的联系人列表
194
+ new_modal:
195
+ label:
196
+ relations: Initially assigned roles
190
197
  one: 联络
191
198
  other: 联系
192
199
  pending:
@@ -14,6 +14,7 @@ module SocialStream
14
14
 
15
15
  module Controllers
16
16
  autoload :Authorship, 'social_stream/controllers/authorship'
17
+ autoload :Avatars, 'social_stream/controllers/avatars'
17
18
  autoload :MarkNotificationsRead, 'social_stream/controllers/mark_notifications_read'
18
19
  autoload :I18nIntegration, 'social_stream/controllers/i18n_integration'
19
20
  autoload :CancanDeviseIntegration, 'social_stream/controllers/cancan_devise_integration'
@@ -1,5 +1,5 @@
1
1
  module SocialStream
2
2
  module Base
3
- VERSION = "2.2.1".freeze
3
+ VERSION = "2.2.2".freeze
4
4
  end
5
5
  end
@@ -10,8 +10,9 @@ module SocialStream
10
10
  private
11
11
 
12
12
  def set_author_ids
13
- resource_params.first[:author_id] = current_subject.try(:actor_id)
13
+ resource_params.first[:author_id] = current_subject.try(:actor_id)
14
14
  resource_params.first[:user_author_id] = current_user.try(:actor_id)
15
+ resource_params.first[:owner_id] ||= current_subject.try(:actor_id)
15
16
  end
16
17
  end
17
18
  end
@@ -0,0 +1,14 @@
1
+ module SocialStream
2
+ module Controllers
3
+ module Avatars
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ def current_avatarable
8
+ @current_avatarable ||=
9
+ Actor.find(params[:actor_id])
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -106,9 +106,9 @@ module SocialStream
106
106
  end
107
107
 
108
108
  if subject != current_user
109
- flash[:notice] ||= ""
110
- flash[:notice] += t('representation.notice',
111
- :subject => subject.name)
109
+ flash.now[:notice] ||= ""
110
+ flash.now[:notice] += t('representation.notice',
111
+ :subject => subject.name)
112
112
  end
113
113
 
114
114
  self.current_subject = subject
@@ -23,6 +23,8 @@ module SocialStream
23
23
 
24
24
  before_filter :authenticate_user!, :only => [:new, :edit, :create, :update, :destroy]
25
25
 
26
+ before_filter :set_post_activity, only: :destroy
27
+
26
28
  after_filter :increment_visit_count, :only => :show
27
29
 
28
30
  load_and_authorize_resource :except => [ :new, :index, :search ]
@@ -40,13 +42,7 @@ module SocialStream
40
42
 
41
43
  render :layout => false
42
44
  end
43
-
44
- def destroy
45
- @post_activity = resource.post_activity
46
-
47
- destroy!
48
- end
49
-
45
+
50
46
  protected
51
47
 
52
48
  def permitted_params
@@ -99,6 +95,9 @@ module SocialStream
99
95
  allowed_params
100
96
  end
101
97
 
98
+ def set_post_activity
99
+ @post_activity = resource.post_activity
100
+ end
102
101
 
103
102
  private
104
103
 
@@ -0,0 +1,148 @@
1
+ namespace :i18n do
2
+ task "common" do
3
+ require 'yaml'
4
+ begin
5
+ require 'social_stream/components'
6
+ rescue LoadError
7
+ # Use this task from social_stream global gem
8
+ # (which defines social_stream/components),
9
+ # as well as from any application using social_stream-base
10
+ end
11
+
12
+ @engines = [ '.' ]
13
+
14
+ if defined? SocialStream::ALL_COMPONENTS
15
+ @engines += SocialStream::ALL_COMPONENTS
16
+ end
17
+ end
18
+
19
+ desc "Synchronize i18n files"
20
+ task "sync" => "common" do
21
+ Hash.class_eval do
22
+ def sync(h)
23
+ en_hash = h.dup
24
+
25
+ each_key do |self_key|
26
+ en_val = en_hash.delete(self_key)
27
+
28
+ case en_val
29
+ when NilClass
30
+ delete(self_key)
31
+ when Hash
32
+ if self[self_key].is_a?(Hash)
33
+ self[self_key].sync(en_val)
34
+ else
35
+ self[self_key] = en_val
36
+ end
37
+ when String
38
+ if self[self_key].nil?
39
+ self[self_key] = en_val
40
+ end
41
+ else
42
+ raise "Unknown key type #{ en_val.inspect }"
43
+ end
44
+ end
45
+
46
+ # Merge missing keys
47
+ merge! en_hash
48
+
49
+ # Order alphabetically
50
+ replace sort_by{ |k, v| k }.inject({}){ |h, a| h[a.first] = a.last; h }
51
+ end
52
+ end
53
+
54
+
55
+ @engines.each do |c|
56
+ path = "#{ c }/config/locales/"
57
+
58
+ files = Dir[path + '*'].select{ |f| f =~ /\/\w+\.yml$/ }
59
+
60
+ en = files.find{ |f| f =~ /\/en.yml$/ }
61
+ files.delete(en)
62
+
63
+ en_h = Psych.load_file(en)
64
+
65
+ files.each do |f|
66
+ h = Psych.load_file(f)
67
+
68
+ # Leave language_name at the begining of the hash
69
+ if c == "base"
70
+ orig_h = h.first.last
71
+ orig_en_h = en_h.first.last.dup
72
+
73
+ language_name = orig_h.delete('language_name')
74
+ language_name_en = orig_en_h.delete('language_name')
75
+ language_name ||= language_name_en
76
+
77
+ orig_h.sync orig_en_h
78
+
79
+ h.first.last.replace({ 'language_name' => language_name }.merge!(orig_h))
80
+ else
81
+ h.first.last.sync en_h.first.last
82
+ end
83
+
84
+ Psych.dump h, File.open(f, 'w')
85
+ end
86
+
87
+ Psych.dump en_h, File.open(en, 'w')
88
+ end
89
+ end
90
+
91
+ desc "Write missing keys of i18n files"
92
+ task "diff" => "common" do
93
+ Hash.class_eval do
94
+ def diff(en_hash)
95
+ diff_hash = {}
96
+
97
+ en_hash.each_key do |en_key|
98
+ en_val = en_hash[en_key]
99
+ self_val = self[en_key]
100
+
101
+ case en_val
102
+ when NilClass
103
+ # Do nothing
104
+ when Hash
105
+ if self_val.is_a?(Hash)
106
+ diff = self_val.diff(en_val)
107
+
108
+ if !diff.empty?
109
+ diff_hash[en_key] = diff
110
+ end
111
+ else
112
+ diff_hash[en_key] = en_val
113
+ end
114
+ when String
115
+ if self_val.nil? || self_val == en_val
116
+ diff_hash[en_key] = en_val
117
+ end
118
+ else
119
+ raise "Unknown key type #{ en_val.inspect }"
120
+ end
121
+ end
122
+
123
+ diff_hash
124
+ end
125
+ end
126
+
127
+ @engines.each do |c|
128
+ path = "#{ c }/config/locales/"
129
+
130
+ files = Dir[path + '*'].select{ |f| f =~ /\/\w+\.yml$/ }
131
+
132
+ en = files.find{ |f| f =~ /\/en.yml$/ }
133
+ files.delete(en)
134
+
135
+ en_h = Psych.load_file(en)
136
+
137
+ files.each do |f|
138
+ h = Psych.load_file(f)
139
+
140
+ diff_hash = h.first.last.diff en_h.first.last
141
+
142
+ if !diff_hash.empty?
143
+ Psych.dump diff_hash, File.open("#{ f }.diff", 'w')
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end