hancock_cms 2.0.0.2 → 2.0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (137) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +4 -0
  3. data/app/assets/images/{devices → hancock/devise}/login-bg.jpg +0 -0
  4. data/app/assets/images/{rails-admin → hancock/rails_admin}/hancock_logo.svg +0 -0
  5. data/app/assets/javascripts/hancock/cms.coffee +1 -1
  6. data/app/assets/javascripts/hancock/rails_admin/cms.ui.coffee +11 -37
  7. data/app/assets/javascripts/hancock/rails_admin/en_ru_switcher.coffee +90 -0
  8. data/app/assets/javascripts/hancock/rails_admin/enum_with_custom.coffee +42 -0
  9. data/app/assets/javascripts/hancock/rails_admin/form_controls_fixed.coffee +44 -0
  10. data/app/assets/javascripts/hancock/rails_admin/leftside_hider.coffee +106 -0
  11. data/app/assets/javascripts/hancock/rails_admin/multiselect.coffee +8 -0
  12. data/app/assets/javascripts/hancock/rails_admin/navigation_dropdown.coffee +25 -0
  13. data/app/assets/javascripts/hancock/rails_admin/navigation_filter.coffee +108 -0
  14. data/app/assets/javascripts/hancock/rails_admin/navigation_scroll.coffee +12 -0
  15. data/app/assets/javascripts/hancock/rails_admin/plugins.coffee.erb +16 -0
  16. data/app/assets/javascripts/jquery.placeholder.js +3 -2
  17. data/app/assets/javascripts/rails_admin/custom/ui.coffee +1 -0
  18. data/app/assets/stylesheets/hancock/cms/devise.sass +4 -1
  19. data/app/assets/stylesheets/hancock/rails_admin/cms.theming.sass +354 -147
  20. data/app/assets/stylesheets/hancock/rails_admin/fieldsets.sass +198 -0
  21. data/app/assets/stylesheets/hancock/rails_admin/plugins.sass.erb +6 -0
  22. data/app/assets/stylesheets/rails_admin/custom/theming.sass +1 -1
  23. data/app/controllers/concerns/hancock/decorators/home.rb +1 -1
  24. data/app/controllers/concerns/hancock/errors.rb +5 -7
  25. data/app/controllers/hancock/registrations_controller.rb +2 -7
  26. data/app/controllers/hancock/sessions_controller.rb +3 -7
  27. data/app/helpers/hancock/powered_helper.rb +3 -3
  28. data/app/helpers/hancock/settings_helper.rb +44 -0
  29. data/app/helpers/rails_admin/application/hancock_helper.rb +19 -0
  30. data/app/helpers/rails_admin/hancock/form_builder.rb +44 -0
  31. data/app/helpers/rails_admin/main/hancock_helper.rb +51 -0
  32. data/app/models/concerns/hancock/boolean_field.rb +7 -2
  33. data/app/models/concerns/hancock/decorators/embedded_element.rb +1 -9
  34. data/app/models/concerns/hancock/enableable.rb +1 -0
  35. data/app/models/concerns/hancock/hash_field.rb +9 -8
  36. data/app/models/concerns/hancock/html_field.rb +6 -3
  37. data/app/models/concerns/hancock/insertion_field.rb +115 -0
  38. data/app/models/concerns/hancock/mappable.rb +1 -0
  39. data/app/models/concerns/hancock/master_collection.rb +31 -0
  40. data/app/models/concerns/hancock/model_localizeable.rb +4 -1
  41. data/app/models/concerns/hancock/rails_admin_patch.rb +22 -3
  42. data/app/models/concerns/hancock/sort_field.rb +26 -3
  43. data/app/models/concerns/hancock/sortable.rb +3 -0
  44. data/app/models/concerns/hancock/user_defined.rb +53 -0
  45. data/app/views/blocks/_footer.html.slim +1 -1
  46. data/app/views/devise/passwords/edit.html.slim +0 -2
  47. data/app/views/devise/passwords/new.html.slim +0 -2
  48. data/app/views/devise/registrations/edit.html.slim +0 -2
  49. data/app/views/devise/registrations/new.html.slim +0 -2
  50. data/app/views/devise/sessions/new.html.slim +0 -2
  51. data/app/views/hancock/home/index.html.slim +4 -1
  52. data/app/views/layouts/application.html.slim +1 -11
  53. data/app/views/layouts/hancock/_assets.html.slim +15 -0
  54. data/app/views/layouts/hancock/devise/confirmations.html.slim +7 -4
  55. data/app/views/layouts/hancock/devise/passwords.html.slim +7 -4
  56. data/app/views/layouts/hancock/devise/registrations.html.slim +7 -4
  57. data/app/views/layouts/hancock/devise/sessions.html.slim +7 -4
  58. data/app/views/layouts/hancock/devise/unlocks.html.slim +7 -4
  59. data/app/views/layouts/rails_admin/_footer.html.slim +2 -2
  60. data/app/views/layouts/rails_admin/_footer_navigation.html.slim +20 -4
  61. data/app/views/layouts/rails_admin/_navigation.html.slim +13 -47
  62. data/app/views/layouts/rails_admin/_secondary_navigation.html.slim +5 -12
  63. data/app/views/layouts/rails_admin/_sidebar_navigation.html.slim +2 -0
  64. data/app/views/layouts/rails_admin/_sidebar_navigation_filter.html.slim +3 -0
  65. data/app/views/layouts/rails_admin/application.html.haml +3 -38
  66. data/app/views/rails_admin/main/_enum_for_settings_kinds.html.slim +24 -0
  67. data/app/views/rails_admin/main/_form_hancock_enum.html.slim +18 -0
  68. data/app/views/rails_admin/main/_form_hancock_enum_with_custom.slim +20 -0
  69. data/app/views/rails_admin/main/_hancock_html.html.slim +2 -2
  70. data/app/views/rails_admin/main/_hancock_html_ml.html.slim +31 -34
  71. data/app/views/rails_admin/main/edit.html.haml +18 -0
  72. data/app/views/rails_admin/main/new.html.haml +17 -0
  73. data/app/views/shared/_admin_link.html.slim +4 -2
  74. data/config/initializers/nested_set_patch.rb +76 -73
  75. data/config/initializers/rails_admin_mongoid_patch.rb +27 -0
  76. data/config/initializers/sprockets_patch.rb +159 -0
  77. data/config/locales/en.hancock.yml +1 -0
  78. data/config/locales/ru.devise.yml +22 -18
  79. data/config/locales/ru.hancock.yml +5 -5
  80. data/config/locales/ru.rails_admin.yml +3 -0
  81. data/hancock_cms.gemspec +7 -2
  82. data/lib/filename_to_slug.rb +0 -20
  83. data/lib/generators/hancock/cms/ability_generator.rb +1 -0
  84. data/lib/generators/hancock/cms/admin_generator.rb +1 -0
  85. data/lib/generators/hancock/cms/application_generator.rb +1 -0
  86. data/lib/generators/hancock/cms/assets_generator.rb +1 -0
  87. data/lib/generators/hancock/cms/layout_generator.rb +1 -0
  88. data/lib/generators/hancock/cms/model_generator.rb +1 -0
  89. data/lib/generators/hancock/cms/models/templates/embedded_element.erb +2 -2
  90. data/lib/generators/hancock/cms/rack_generator.rb +1 -0
  91. data/lib/generators/hancock/cms/raven_generator.rb +13 -0
  92. data/lib/generators/hancock/cms/robots_generator.rb +1 -0
  93. data/lib/generators/hancock/cms/scripts_generator.rb +1 -0
  94. data/lib/generators/hancock/cms/setup_generator.rb +146 -33
  95. data/lib/generators/hancock/cms/templates/Gemfile.erb +4 -5
  96. data/lib/generators/hancock/cms/templates/ability.erb +1 -1
  97. data/lib/generators/hancock/cms/templates/admin.erb +12 -4
  98. data/lib/generators/hancock/cms/templates/hancock_cms.erb +6 -3
  99. data/lib/generators/hancock/cms/templates/model.erb +5 -6
  100. data/lib/generators/hancock/cms/templates/raven.erb +13 -0
  101. data/lib/generators/hancock/cms/templates/robots.txt.erb +6 -2
  102. data/lib/generators/hancock/cms/templates/scripts/db_dump.sh.erb +1 -1
  103. data/lib/generators/hancock/cms/unicorn_god_generator.rb +1 -0
  104. data/lib/generators/hancock/cms/utils.rb +2 -0
  105. data/lib/hancock/admin.rb +153 -21
  106. data/lib/hancock/admin/embedded_element.rb +7 -2
  107. data/lib/hancock/configuration.rb +49 -4
  108. data/lib/hancock/controller.rb +1 -1
  109. data/lib/hancock/engine.rb +32 -36
  110. data/lib/hancock/model.rb +10 -0
  111. data/lib/hancock/models/embedded_element.rb +2 -0
  112. data/lib/hancock/models/mongoid/embedded_element.rb +17 -0
  113. data/lib/hancock/plugin_configuration.rb +1 -1
  114. data/lib/hancock/rails_admin_ext/config.rb +21 -4
  115. data/lib/hancock/rails_admin_ext/hancock_array.rb +19 -0
  116. data/lib/hancock/rails_admin_ext/hancock_enum.rb +33 -0
  117. data/lib/hancock/rails_admin_ext/hancock_enum_with_custom.rb +34 -0
  118. data/lib/hancock/rails_admin_ext/hancock_hash.rb +8 -1
  119. data/lib/hancock/rails_admin_ext/hancock_html.rb +17 -2
  120. data/lib/hancock/rails_admin_ext/hancock_multiselect.rb +1 -5
  121. data/lib/hancock/rails_admin_ext/hancock_slugs.rb +2 -6
  122. data/lib/hancock/rails_admin_ext/patches/field_patch.rb +2 -1
  123. data/lib/hancock/rails_admin_ext/patches/fieldset_patch.rb +14 -0
  124. data/lib/hancock/rails_admin_ext/patches/group_patch.rb +9 -0
  125. data/lib/hancock/rails_admin_ext/patches/hancock_cms_group.rb +2 -0
  126. data/lib/hancock/rails_admin_ext/patches/has_fields.rb +27 -0
  127. data/lib/hancock/rails_admin_ext/patches/navigation_patch.rb +25 -0
  128. data/lib/hancock/rails_admin_settings_patch.rb +219 -0
  129. data/lib/hancock/version.rb +1 -1
  130. data/lib/hancock_cms.rb +12 -9
  131. data/lib/manual_slug/active_record.rb +8 -8
  132. data/lib/manual_slug/mongoid.rb +6 -1
  133. data/lib/rails_admin/custom_show_in_app.rb +21 -32
  134. data/template.rb +19 -20
  135. metadata +104 -12
  136. data/app/controllers/concerns/hancock/no_cache.rb +0 -12
  137. data/app/models/concerns/hancock/cacheable.rb +0 -51
@@ -0,0 +1,159 @@
1
+ require 'sprockets/directive_processor'
2
+
3
+ class Sprockets::DirectiveProcessor
4
+ def _call(input)
5
+
6
+ @environment = input[:environment]
7
+ @uri = input[:uri]
8
+ @filename = input[:filename]
9
+ @dirname = File.dirname(@filename)
10
+ @content_type = input[:content_type]
11
+ @required = Set.new(input[:metadata][:required])
12
+ @stubbed = Set.new(input[:metadata][:stubbed])
13
+ @links = Set.new(input[:metadata][:links])
14
+ @dependencies = Set.new(input[:metadata][:dependencies])
15
+
16
+ if Hancock.config.erb2coffee_assets.include?(input[:name])
17
+ data, directives = process_source(::ERB.new(input[:data], nil, '-').result)
18
+ else
19
+ data, directives = process_source(input[:data])
20
+ end
21
+
22
+ process_directives(directives)
23
+
24
+ { data: data,
25
+ required: @required,
26
+ stubbed: @stubbed,
27
+ links: @links,
28
+ dependencies: @dependencies }
29
+ end
30
+ end
31
+
32
+ ##### maybe it will help in future
33
+
34
+ # require "sprockets"
35
+ #
36
+ # class Hancock::ErbToCoffeeSprocketsExtension
37
+ # def initialize(filename, &block)
38
+ # @filename = filename
39
+ # @source = block.call
40
+ # end
41
+ #
42
+ # def render(context, empty_hash_wtf)
43
+ # self.class.run(@filename, @source, context)
44
+ # end
45
+ #
46
+ # def self.run(filename, source, context)
47
+ # puts source if filename =~ /plugins/i
48
+ # result = ::ERB.new(source, nil, '-').result
49
+ # puts "VVVVVVVVVVVVVVV" if filename =~ /plugins/i
50
+ # puts result if filename =~ /plugins/i
51
+ # puts "" if filename =~ /plugins/i
52
+ # puts "" if filename =~ /plugins/i
53
+ # result
54
+ # end
55
+ #
56
+ # def self.call(input)
57
+ # filename = input[:filename]
58
+ # source = input[:data]
59
+ # context = input[:environment].context_class.new(input)
60
+ #
61
+ # result = run(filename, source, context)
62
+ # context.metadata.merge(data: result)
63
+ # end
64
+ # end
65
+ #
66
+ # require 'sprockets/processing'
67
+ # # extend Sprockets::Processing
68
+ #
69
+ # # Sprockets.unregister_preprocessor('text/coffeescript', Sprockets::DirectiveProcessor)
70
+ # # Sprockets.register_preprocessor('text/coffeescript', Sprockets::DirectiveProcessor.new(comments: ["#", ["###", "###"]]))
71
+ # # Sprockets.register_preprocessor 'text/coffeescript', :erb_to_coffee do |context, data|
72
+ # # puts data.inspect
73
+ # # end
74
+ #
75
+ # Sprockets.unregister_preprocessor('text/coffeescript', Sprockets::DirectiveProcessor)
76
+ # Sprockets::register_preprocessor 'application/javascript', Hancock::ErbToCoffeeSprocketsExtension
77
+ # # Sprockets::register_preprocessor 'text/coffeescript', Hancock::ErbToCoffeeSprocketsExtension
78
+ # Sprockets.register_preprocessor('text/coffeescript', Sprockets::DirectiveProcessor.new(comments: ["#", ["###", "###"]]))
79
+ #
80
+ # puts Sprockets.preprocessors
81
+ #
82
+ # # require 'sprockets'
83
+ # # require 'sprockets/context'
84
+ # # require 'sprockets/erb_processor'
85
+ # # class Sprockets::ERBProcessor
86
+ # # def call(input)
87
+ # # if input[:filename] =~ /(plugins|cms)/
88
+ # # puts "___"
89
+ # # puts input[:data]
90
+ # # engine = ::ERB.new(input[:data], nil, '%')
91
+ # # puts "VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV"
92
+ # # puts Sprockets::CoffeeScriptProcessor::VERSION
93
+ # # puts engine.result
94
+ # # puts ""
95
+ # # puts ""
96
+ # # else
97
+ # # engine = ::ERB.new(input[:data], nil, '-')
98
+ # # end
99
+ # # if Sprockets::CoffeeScriptProcessor::VERSION == "2"
100
+ # # engine.filename = input[:filename]
101
+ # # context = input[:environment].context_class.new(input)
102
+ # # klass = (class << context; self; end)
103
+ # # klass.const_set(:ENV, context.env_proxy)
104
+ # # klass.class_eval(&@block) if @block
105
+ # # data = engine.result(context.instance_eval('binding'))
106
+ # # context.metadata.merge(data: data)
107
+ # #
108
+ # # elsif Sprockets::CoffeeScriptProcessor::VERSION == "1"
109
+ # # engine = ::ERB.new(input[:data], nil, '<>')
110
+ # # context = input[:environment].context_class.new(input)
111
+ # # klass = (class << context; self; end)
112
+ # # klass.class_eval(&@block) if @block
113
+ # # engine.def_method(klass, :_evaluate_template, input[:filename])
114
+ # # data = context._evaluate_template
115
+ # # context.metadata.merge(data: data)
116
+ # # end
117
+ # #
118
+ # # end
119
+ # # end
120
+ # #
121
+ # # require 'sprockets/coffee_script_processor'
122
+ # # module Sprockets
123
+ # # module CoffeeScriptProcessor
124
+ # #
125
+ # # def self.call(input)
126
+ # # data = input[:data]
127
+ # # puts "CoffeeScriptProcessor"
128
+ # # puts VERSION
129
+ # # puts input.inspect
130
+ # # puts data.inspect
131
+ # # puts
132
+ # # puts
133
+ # # if VERSION == "2"
134
+ # #
135
+ # # js, map = input[:cache].fetch([self.cache_key, data]) do
136
+ # # result = Autoload::CoffeeScript.compile(
137
+ # # data,
138
+ # # sourceMap: true,
139
+ # # sourceFiles: [File.basename(input[:filename])],
140
+ # # generatedFile: input[:filename]
141
+ # # )
142
+ # # [result['js'], JSON.parse(result['v3SourceMap'])]
143
+ # # end
144
+ # #
145
+ # # map = SourceMapUtils.format_source_map(map, input)
146
+ # # map = SourceMapUtils.combine_source_maps(input[:metadata][:map], map)
147
+ # #
148
+ # # { data: js, map: map }
149
+ # #
150
+ # # elsif VERSION == "1"
151
+ # # input[:cache].fetch([self.cache_key, data]) do
152
+ # # Autoload::CoffeeScript.compile(data)
153
+ # # end
154
+ # #
155
+ # # end
156
+ # #
157
+ # # end
158
+ # # end
159
+ # # end
@@ -4,6 +4,7 @@ en:
4
4
  cms: "CMS"
5
5
  menu: "Menu"
6
6
  settings: 'Settings'
7
+ insertions: "Insertions"
7
8
  news: 'News'
8
9
  with_final_slash: "should begin with a slash"
9
10
  page_url_regex: "Regular expression to check if page is current"
@@ -1,9 +1,9 @@
1
1
  ru:
2
2
  devise:
3
3
  confirmations:
4
- confirmed: Ваша учётная запись подтверждена. Теперь вы вошли в систему.
5
- send_instructions: В течение нескольких минут вы получите письмо с инструкциями по подтверждению вашей учётной записи.
6
- send_paranoid_instructions: Если ваш адрес e-mail есть в нашей базе данных, то в течение нескольких минут вы получите письмо с инструкциями по подтверждению вашей учётной записи.
4
+ confirmed: Ваша учётная запись подтверждена. Теперь Вы вошли в систему.
5
+ send_instructions: В течение нескольких минут Вы получите письмо с инструкциями по подтверждению Вашей учётной записи.
6
+ send_paranoid_instructions: Если Ваш адрес e-mail есть в нашей базе данных, то в течение нескольких минут Вы получите письмо с инструкциями по подтверждению Вашей учётной записи.
7
7
  failure:
8
8
  already_authenticated: Вы уже вошли в систему.
9
9
  inactive: Ваша учётная запись ещё не активирована.
@@ -13,7 +13,7 @@ ru:
13
13
  not_found_in_database: Неверный адрес e-mail или пароль.
14
14
  timeout: Ваш сеанс закончился. Пожалуйста, войдите в систему снова.
15
15
  unauthenticated: Вам необходимо войти в систему или зарегистрироваться.
16
- unconfirmed: Вы должны подтвердить вашу учётную запись.
16
+ unconfirmed: Вы должны подтвердить Вашу учётную запись.
17
17
  mailer:
18
18
  confirmation_instructions:
19
19
  subject: Инструкции по подтверждению учётной записи
@@ -25,30 +25,34 @@ ru:
25
25
  failure: Вы не можете войти в систему с учётной записью из %{kind}, т.к. "%{reason}".
26
26
  success: Вход в систему выполнен с учётной записью из %{kind}.
27
27
  passwords:
28
- no_token: Доступ к этой странице возможен только по ссылке из письма о восстановлении пароля. Если Вы пришли по такой ссылке, пожалуйста убедитесь что Вы скопировали всю ссылку целиком.
29
- send_instructions: В течение нескольких минут вы получите письмо с инструкциями по восстановлению вашего пароля.
30
- send_paranoid_instructions: Если ваш адрес e-mail есть в нашей базе данных, то в течение нескольких минут вы получите письмо с инструкциями по восстановлению вашего пароля.
31
- updated: Ваш пароль изменён. Теперь вы вошли в систему.
28
+ no_token: Доступ к этой странице возможен только по ссылке из письма о восстановлении пароля. Если Выпришли по такой ссылке, пожалуйста убедитесь что Вы скопировали всю ссылку целиком.
29
+ send_instructions: В течение нескольких минут Вы получите письмо с инструкциями по восстановлению Вашего пароля.
30
+ send_paranoid_instructions: Если Ваш адрес e-mail есть в нашей базе данных, то в течение нескольких минут Вы получите письмо с инструкциями по восстановлению Вашего пароля.
31
+ updated: Ваш пароль изменён. Теперь Вы вошли в систему.
32
32
  updated_not_active: Ваш пароль изменен.
33
33
  registrations:
34
- destroyed: До свидания! Ваша учётная запись удалена. Надеемся снова увидеть вас.
34
+ destroyed: До свидания! Ваша учётная запись удалена. Надеемся снова увидеть Вас.
35
35
  signed_up: Добро пожаловать! Вы успешно зарегистрировались.
36
- signed_up_but_inactive: Вы успешно зарегистрированы. Однако, вы не можете войти в систему, потому что ваша учетная запись не активирована.
37
- signed_up_but_locked: Вы успешно зарегистрированы. Однако, вы не можете войти в систему, потому что ваша учетная запись заблокирована.
38
- signed_up_but_unconfirmed: Письмо со ссылкой для подтверждения было отправлено на ваш e-mail. Пожалуйста, перейдите по ссылке, чтобы подтвердить вашу учетную запись.
39
- update_needs_confirmation: Вы успешно обновили данные вашей учетной записи, но нам нужно проверить ваш новый адрес e-mail. Пожалуйста, проверьте ваш почтовый ящик и перейдите по ссылке, чтобы закончить процедуру проверки вашего нового адреса e-mail.
36
+ signed_up_but_inactive: Вы успешно зарегистрированы. Однако, Вы не можете войти в систему, потому что Ваша учетная запись не активирована.
37
+ signed_up_but_locked: Вы успешно зарегистрированы. Однако, Вы не можете войти в систему, потому что Ваша учетная запись заблокирована.
38
+ signed_up_but_unconfirmed: Письмо со ссылкой для подтверждения было отправлено на Ваш e-mail. Пожалуйста, перейдите по ссылке, чтобы подтвердить Вашу учетную запись.
39
+ update_needs_confirmation: Вы успешно обновили данные Вашей учетной записи, но нам нужно проверить Ваш новый адрес e-mail. Пожалуйста, проверьте Ваш почтовый ящик и перейдите по ссылке, чтобы закончить процедуру проверки Вашего нового адреса e-mail.
40
40
  updated: Ваша учётная запись изменена.
41
41
  sessions:
42
42
  signed_in: Вход в систему выполнен.
43
43
  signed_out: Выход из системы выполнен.
44
44
  unlocks:
45
- send_instructions: В течение нескольких минут вы получите письмо с инструкциями по разблокировке вашей учётной записи.
46
- send_paranoid_instructions: Если ваша учётная запись существует, то в течение нескольких минут вы получите письмо с инструкциями по её разблокировке.
47
- unlocked: Ваша учётная запись разблокирована. Теперь вы можете войти в систему.
45
+ send_instructions: В течение нескольких минут Вы получите письмо с инструкциями по разблокировке Вашей учётной записи.
46
+ send_paranoid_instructions: Если Ваша учётная запись существует, то в течение нескольких минут Вы получите письмо с инструкциями по её разблокировке.
47
+ unlocked: Ваша учётная запись разблокирована. Теперь Вы можете войти в систему.
48
48
  failure:
49
49
  user:
50
- not_found_in_database: Пользователь не найден в базе
51
- invalid: Неверный пароль
50
+ # not secure
51
+ # not_found_in_database: Пользователь не найден в базе
52
+ # invalid: Неверный пароль.
53
+ # more secure
54
+ not_found_in_database: Неверный адрес e-mail или пароль.
55
+ invalid: Неверный адрес e-mail или пароль.
52
56
  unauthenticated: Необходимо авторизоваться
53
57
  unconfirmed: 'Необходимо подтвердить адрес электронной почты'
54
58
  errors:
@@ -2,17 +2,17 @@ ru:
2
2
  hancock:
3
3
  url: URL
4
4
  content: "Контент"
5
- cache: Кеширование
6
- gallery: "Галерея"
5
+ categories: "Разделы"
7
6
  cms: "CMS"
8
- menu: "Меню"
7
+ # menu: "Меню"
9
8
  settings: 'Настройки'
9
+ insertions: "Возможные вставки"
10
10
  with_final_slash: "c начальным слешем"
11
11
  page_url_regex: "Регулярное выражение, по которому определяется является ли этот пункт активным"
12
12
  final_in_menu: "В меню сразу отдается конечная ссылка"
13
13
  map: 'Карта'
14
- sitemap: 'Карта сайта'
15
- sitemap_data: 'Данные для карты сайта'
14
+ # sitemap: 'Карта сайта'
15
+ # sitemap_data: 'Данные для карты сайта'
16
16
  edit: Редактировать
17
17
  send: Отправить
18
18
  format_time: "%d.%m.%Y"
@@ -31,6 +31,7 @@ ru:
31
31
  misc:
32
32
  filter_date_format: "dd.mm.yyyy"
33
33
  search: "Поиск"
34
+ search_or_add_yours: "Поиск/новый элемент"
34
35
  filter: "Фильтрация"
35
36
  refresh: "Обновить"
36
37
  show_all: "Показать все"
@@ -130,6 +131,8 @@ ru:
130
131
  show_in_app:
131
132
  title: 'В приложении'
132
133
  menu: "Показать на сайте"
134
+ logout:
135
+ confirm: "Вы точно хотите выйти?"
133
136
  form:
134
137
  cancel: "Отмена"
135
138
  basic_info: "Основное"
data/hancock_cms.gemspec CHANGED
@@ -22,6 +22,8 @@ Gem::Specification.new do |spec|
22
22
 
23
23
  spec.add_dependency 'rails', ['>= 5.0.0', '< 6.0']
24
24
 
25
+ spec.add_dependency 'sprockets', '~> 3.7.1'
26
+
25
27
  spec.add_dependency 'jquery-rails'
26
28
  spec.add_dependency 'simple_form'
27
29
  # spec.add_dependency 'glebtv-simple_captcha'
@@ -32,15 +34,18 @@ Gem::Specification.new do |spec|
32
34
  spec.add_dependency 'ckeditor'
33
35
  spec.add_dependency 'geocoder'
34
36
 
35
- spec.add_dependency 'rails_admin', '>= 1.0.0'
37
+ spec.add_dependency 'rails_admin', '1.1.1'
36
38
  spec.add_dependency 'rails_admin_nested_set'
37
39
  spec.add_dependency 'rails_admin_toggleable'
38
40
 
39
- spec.add_dependency 'ack_rails_admin_settings', '~> 1.2'
41
+ spec.add_dependency 'ack_rails_admin_settings', '~> 1.2.2'
42
+ spec.add_dependency 'safe_yaml'
40
43
 
41
44
  spec.add_dependency 'kaminari'
45
+ spec.add_dependency 'kaminari-actionview'
42
46
 
43
47
  spec.add_dependency 'codemirror-rails'
44
48
 
45
49
  spec.add_dependency 'scrollbar-rails'
50
+ spec.add_dependency 'stickykit-rails'
46
51
  end
@@ -10,23 +10,3 @@ class String
10
10
  s
11
11
  end
12
12
  end
13
- #
14
- # module FilenameToSlug
15
- # extend ActiveSupport::Concern
16
- # included do
17
- # before_post_process :filename_to_slug
18
- # end
19
- #
20
- # def filename_to_slug
21
- # if self.class.attachment_definitions
22
- # self.class.attachment_definitions.each do |k,v|
23
- # if self.send(k).file?
24
- # full_file_name = self.send("#{k}_file_name")
25
- # extension = File.extname(full_file_name)[1..-1]
26
- # file_name = full_file_name[0..full_file_name.size-extension.size-1]
27
- # self.send("#{k}").instance_write(:file_name, "#{file_name.filename_to_slug}.#{extension.filename_to_slug}")
28
- # end
29
- # end
30
- # end
31
- # end
32
- # end
@@ -10,5 +10,6 @@ module Hancock::Cms
10
10
  def install
11
11
  template 'ability.erb', 'app/models/ability.rb'
12
12
  end
13
+
13
14
  end
14
15
  end
@@ -17,5 +17,6 @@ module Hancock::Cms
17
17
  # route("mount RailsAdmin::Engine => '/#{namespace}', as: 'rails_admin'")
18
18
  template 'admin.erb', 'config/initializers/rails_admin.rb'
19
19
  end
20
+
20
21
  end
21
22
  end
@@ -10,5 +10,6 @@ module Hancock::Cms
10
10
  def install
11
11
  template "application.erb", "config/application.rb"
12
12
  end
13
+
13
14
  end
14
15
  end
@@ -31,5 +31,6 @@ module Hancock::Cms
31
31
  application_coffee_path
32
32
  ]
33
33
  end
34
+
34
35
  end
35
36
  end
@@ -10,5 +10,6 @@ module Hancock::Cms
10
10
  def layout
11
11
  template('../app/views/layouts/application.html.slim', 'app/views/layouts/application.html.slim')
12
12
  end
13
+
13
14
  end
14
15
  end
@@ -35,5 +35,6 @@ module Hancock::Cms
35
35
  def underscored_pluralized_class_name
36
36
  underscored_class_name.pluralize
37
37
  end
38
+
38
39
  end
39
40
  end
@@ -1,6 +1,6 @@
1
1
  class <%= camelcased_class_name %> < Hancock::EmbeddedElement
2
- embedded_in :<%= underscored_parent_class_name %>, class_name: "<%= camelcased_parent_class_name %>"
3
2
 
3
+ embedded_in :<%= underscored_parent_class_name %>, class_name: "<%= camelcased_parent_class_name %>"
4
4
  def self.find(id)
5
5
  find_through(<%= camelcased_parent_class_name %>, '<%= underscored_pluralized_class_name %>', id)
6
6
  end
@@ -30,7 +30,7 @@ class <%= camelcased_class_name %> < Hancock::EmbeddedElement
30
30
  # def self.rails_admin_user_defined_visible_actions
31
31
  # [].freeze
32
32
  # end
33
-
33
+
34
34
  def self.rails_admin_add_fields
35
35
  super
36
36
  end
@@ -8,5 +8,6 @@ module Hancock::Cms
8
8
  def install
9
9
  template('rack.erb', 'config/initializers/rack.rb')
10
10
  end
11
+
11
12
  end
12
13
  end
@@ -0,0 +1,13 @@
1
+ require 'rails/generators'
2
+
3
+ module Hancock::Cms
4
+ class RavenGenerator < Rails::Generators::Base
5
+ source_root File.expand_path('../templates', __FILE__)
6
+
7
+ desc 'Hancock CMS Raven Config generator'
8
+ def install
9
+ template 'raven.erb', "config/initializers/raven.rb"
10
+ end
11
+
12
+ end
13
+ end
@@ -10,5 +10,6 @@ module Hancock::Cms
10
10
  def install
11
11
  template('robots.txt.erb', 'public/robots.txt')
12
12
  end
13
+
13
14
  end
14
15
  end
@@ -27,5 +27,6 @@ module Hancock::Cms
27
27
  FileUtils.chmod(0755, "#{destination_root}/scripts/#{script_name}") # chmod: 0755 in prev line doesnt work
28
28
  end
29
29
  end
30
+
30
31
  end
31
32
  end
@@ -7,27 +7,51 @@ module Hancock::Cms
7
7
  desc 'Hancock CMS Carcass generator'
8
8
  def install
9
9
 
10
+ def ask_with_timeout(question, timeout = 5)
11
+ ask(question)
12
+ # # temp
13
+ # begin
14
+ # Timeout::timeout(timeout) {
15
+ # ask("#{question} | U have only #{timeout} second(s)!")
16
+ # }
17
+ # rescue
18
+ # puts ""
19
+ # ""
20
+ # end
21
+ end
22
+
10
23
  ####### DEVISE #######
11
24
 
12
- generate "devise:install"
25
+ generate "devise:install" if ["yes", "y"].include?(ask_with_timeout("generate `devise:install`?(y or yes)").downcase.strip)
13
26
  gsub_file 'config/initializers/devise.rb', "'please-change-me-at-config-initializers-devise@example.com'", "'noreply@#{app_name.dasherize.downcase}.ru'"
27
+
28
+ if ["yes", "y"].include?(ask_with_timeout("Set Hancock's layout for devise? (y or yes)").downcase.strip)
29
+ _sessions_layout = Devise::SessionsController._layout == "hancock/devise/sessions"
30
+ _registration_layout = Devise::RegistrationsController._layout == "hancock/devise/registrations"
31
+ _confirmations_layout = Devise::ConfirmationsController._layout == "hancock/devise/confirmations"
32
+ _unlocks_layout = Devise::UnlocksController._layout == "hancock/devise/unlocks"
33
+ _passwords_layout = Devise::PasswordsController._layout == "hancock/devise/passwords"
34
+ if !_sessions_layout or !_registration_layout or !_confirmations_layout or !_unlocks_layout or !_passwords_layout
14
35
  inject_into_file 'config/initializers/devise.rb', after: /^end/ do <<-TEXT
15
36
 
16
37
  Rails.application.config.to_prepare do
17
- Devise::SessionsController.layout "hancock/devise/sessions"
18
- Devise::RegistrationsController.layout "hancock/devise/registrations"
19
- Devise::ConfirmationsController.layout "hancock/devise/confirmations"
20
- Devise::UnlocksController.layout "hancock/devise/unlocks"
21
- Devise::PasswordsController.layout "hancock/devise/passwords"
38
+ #{'Devise::SessionsController.layout "hancock/devise/sessions"' unless _sessions_layout }
39
+ #{'Devise::RegistrationsController.layout "hancock/devise/registrations"' unless _registration_layout }
40
+ #{'Devise::ConfirmationsController.layout "hancock/devise/confirmations"' unless _confirmations_layout }
41
+ #{'Devise::UnlocksController.layout "hancock/devise/unlocks"' unless _unlocks_layout }
42
+ #{'Devise::PasswordsController.layout "hancock/devise/passwords"' unless _passwords_layout }
22
43
  end
23
44
  TEXT
24
45
  end
25
-
26
- generate "devise", "User"
46
+ end
47
+ end
48
+ generate "devise", "User", "--routes=false" if ["yes", "y"].include?(ask_with_timeout("generate `devise User --routes=false`?(y or yes)").downcase.strip)
27
49
 
28
50
 
29
51
  ####### ROUTES #######
30
52
 
53
+
54
+ if ["yes", "y"].include?(ask_with_timeout("Set Hancock's routes? (y or yes)").downcase.strip)
31
55
  remove_file 'config/routes.rb'
32
56
  create_file 'config/routes.rb' do <<-TEXT
33
57
  Rails.application.routes.draw do
@@ -37,31 +61,95 @@ Rails.application.routes.draw do
37
61
  end
38
62
  TEXT
39
63
  end
64
+ end
40
65
 
41
66
 
42
67
  ####### INITIALIZERS #######
43
68
 
69
+ add_assets_precompiled = ["*.svg", 'ckeditor/*', 'codemirror.js', 'codemirror.css', 'codemirror/**/*']
70
+ if (Rails.application.config.assets.precompile & add_assets_precompiled).length < add_assets_precompiled.length
44
71
  inject_into_file 'config/initializers/assets.rb', before: /\z/ do <<-TEXT
45
72
  Rails.application.config.assets.precompile += %w( *.svg )
46
73
  Rails.application.config.assets.precompile += %w( ckeditor/* )
47
74
  Rails.application.config.assets.precompile += %w( codemirror.js codemirror.css codemirror/**/* )
48
75
  TEXT
49
76
  end
77
+ end
50
78
 
51
- gsub_file 'config/initializers/backtrace_silencers.rb',
52
- "# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }",
53
- "Rails.backtrace_cleaner.add_silencer { |line| line =~ /lib\\/(haml|slim|sass|scss|coffee|compass)/ }"
54
79
 
55
80
  if mongoid
56
- generate "ckeditor:install", "--orm=mongoid", "--backend=paperclip"
81
+ if defined?(Paperclip)
82
+ generate "ckeditor:install", "--orm=mongoid", "--backend=paperclip" if ["yes", "y"].include?(ask_with_timeout("generate `ckeditor:install --orm=mongoid --backend=paperclip`?(y or yes)").downcase.strip)
83
+ require 'ckeditor/orm/mongoid'
84
+ require Rails.root.join("app", "models", "ckeditor", "asset.rb")
85
+ if defined?(Ckeditor::Asset)
86
+ unless Ckeditor::Asset < Hancock::Model
87
+ inject_into_file 'app/models/ckeditor/asset.rb', before: /^end/ do <<-TEXT
88
+ include Hancock::Model
89
+ TEXT
90
+ end
91
+ end
92
+ end
93
+ if ["yes", "y"].include?(ask_with_timeout("Set Hancock's config for Ckeditor::Picture? (y or yes)").downcase.strip)
94
+ remove_file 'app/models/ckeditor/picture.rb'
95
+ create_file 'app/models/ckeditor/picture.rb' do <<-TEXT
96
+ class Ckeditor::Picture < Ckeditor::Asset
97
+ # has_mongoid_attached_file :data,
98
+ # url: '/ckeditor_assets/pictures/:id/:style_:basename.:extension',
99
+ # path: ':rails_root/public/ckeditor_assets/pictures/:id/:style_:basename.:extension',
100
+ # styles: { content: '800>', thumb: '118x100#' }
101
+
102
+ include Hancock::Gallery::Paperclipable
103
+ hancock_cms_attached_file :data,
104
+ url: '/ckeditor_assets/pictures/:id/:style/:basename.:extension',
105
+ path: ':rails_root/public/ckeditor_assets/pictures/:id/:style/:basename.:extension'
106
+ def data_styles
107
+ if data_svg?
108
+ {}
109
+ else
110
+ { content: '800>', thumb: '118x100#' }
111
+ end
112
+ end
113
+
114
+ validates_attachment_size :data, less_than: 2.megabytes
115
+ validates_attachment_presence :data
116
+ validates_attachment_content_type :data, content_type: /\\Aimage/
117
+
118
+ def url_content
119
+ # url(:content)
120
+ if data_svg?
121
+ url
122
+ else
123
+ url(:content)
124
+ end
125
+ end
126
+
127
+ def url_thumb
128
+ # url(:thumb)
129
+ if data_svg?
130
+ url
131
+ else
132
+ url(:thumb)
133
+ end
134
+ end
135
+ end
136
+ TEXT
137
+ end
138
+ end
139
+ end
140
+
57
141
  else
58
- generate "ckeditor:install", "--orm=active_record", "--backend=paperclip"
142
+ if defined?(Paperclip)
143
+ generate "ckeditor:install", "--orm=active_record", "--backend=paperclip" if ["yes", "y"].include?(ask_with_timeout("generate `ckeditor:install --orm=active_record --backend=paperclip`?(y or yes)").downcase.strip)
144
+ end
145
+ end
146
+ if File.exists?(Rails.root.join 'config/initializers/ckeditor.rb')
147
+ gsub_file 'config/initializers/ckeditor.rb', "# config.image_file_types = %w(jpg jpeg png gif tiff)", "config.image_file_types = %w(jpg jpeg png gif tiff svg)"
148
+ gsub_file 'config/initializers/ckeditor.rb', "# config.authorize_with :cancan", "# config.authorize_with :cancancan"
149
+ gsub_file 'config/initializers/ckeditor.rb', "# config.assets_languages = ['en', 'uk']", "config.assets_languages = ['en', 'ru']"
59
150
  end
60
- gsub_file 'config/initializers/ckeditor.rb', "# config.image_file_types = %w(jpg jpeg png gif tiff)", "config.image_file_types = %w(jpg jpeg png gif tiff svg)"
61
- gsub_file 'config/initializers/ckeditor.rb', "# config.authorize_with :cancan", "config.authorize_with :cancancan"
62
- gsub_file 'config/initializers/ckeditor.rb', "# config.assets_languages = ['en', 'uk']", "config.assets_languages = ['en', 'ru']"
63
151
 
64
- if mongoid
152
+ if mongoid and ["yes", "y"].include?(ask_with_timeout("Set Hancock's config for cookies_serializer? (y or yes)").downcase.strip)
65
153
  remove_file 'config/initializers/cookies_serializer.rb'
66
154
  create_file 'config/initializers/cookies_serializer.rb' do <<-TEXT
67
155
  # Be sure to restart your server when you modify this file.
@@ -77,7 +165,7 @@ gsub_file 'config/initializers/filter_parameter_logging.rb', "[:password]", "[:p
77
165
 
78
166
  # generate 'paperclip_optimizer:install'
79
167
  # remove_file 'config/initializers/paperclip_optimizer.rb'
80
- # generate "hancock:cms:paperclip_optimizer"
168
+ generate "hancock:cms:paperclip_optimizer" if ["yes", "y"].include?(ask_with_timeout("generate `hancock:cms:paperclip_optimizer`? (y or yes)").downcase.strip)
81
169
 
82
170
  # generate 'rails_email_preview:install'
83
171
  # remove_file 'app/mailer_previews/contact_mailer_preview.rb'
@@ -90,12 +178,13 @@ gsub_file 'config/initializers/filter_parameter_logging.rb', "[:password]", "[:p
90
178
  # TEXT
91
179
  # end
92
180
 
93
- generate "hancock:cms:config"
181
+ generate "hancock:cms:config" if ["yes", "y"].include?(ask_with_timeout("generate `hancock:cms:config`? (y or yes)").downcase.strip)
94
182
 
95
- generate "hancock:cms:rack"
183
+ generate "hancock:cms:rack" if ["yes", "y"].include?(ask_with_timeout("generate `hancock:cms:rack`? (y or yes)").downcase.strip)
96
184
 
97
- generate "hancock:cms:admin"
185
+ generate "hancock:cms:admin" if ["yes", "y"].include?(ask_with_timeout("generate `hancock:cms:admin`? (y or yes)").downcase.strip)
98
186
 
187
+ if ["yes", "y"].include?(ask_with_timeout("Set Hancock's config for session_store? (y or yes)").downcase.strip)
99
188
  remove_file 'config/initializers/session_store.rb'
100
189
  if mongoid
101
190
  create_file 'config/initializers/session_store.rb' do <<-TEXT
@@ -115,16 +204,20 @@ Rails.application.config.session_store :active_record_store
115
204
  TEXT
116
205
  end
117
206
  end
207
+ end
118
208
 
119
209
  # unless mongoid
120
210
  # generate 'simple_captcha'
121
211
  # end
122
212
 
123
- generate "simple_form:install"
213
+ generate "simple_form:install" if ["yes", "y"].include?(ask_with_timeout("generate `simple_form:install`? (y or yes)").downcase.strip)
214
+
124
215
 
125
216
 
126
217
  ####### CONTROLLERS #######
127
218
 
219
+
220
+ unless ApplicationController < Hancock::Controller
128
221
  remove_file 'app/controllers/application_controller.rb'
129
222
  create_file 'app/controllers/application_controller.rb' do <<-TEXT
130
223
  class ApplicationController < ActionController::Base
@@ -132,12 +225,19 @@ class ApplicationController < ActionController::Base
132
225
  end
133
226
  TEXT
134
227
  end
228
+ end
135
229
 
136
230
 
137
231
  ####### MODELS #######
138
232
 
139
- generate "hancock:cms:ability"
233
+ generate "hancock:cms:ability" if ["yes", "y"].include?(ask_with_timeout("generate `hancock:cms:ability`? (y or yes)").downcase.strip)
140
234
 
235
+ gsub_user_rb = begin
236
+ (User < Hancock::Model).nil?
237
+ rescue
238
+ true
239
+ end
240
+ if gsub_user_rb
141
241
  gsub_file 'app/models/user.rb', '# :confirmable, :lockable, :timeoutable and :omniauthable' do <<-TEXT
142
242
  include Hancock::Model
143
243
  include Hancock::Enableable
@@ -164,6 +264,7 @@ include Hancock::Model
164
264
  TEXT
165
265
  end
166
266
 
267
+ if ["yes", "y"].include?(ask_with_timeout("Set Hancock's User model? (y or yes)").downcase.strip)
167
268
  gsub_file 'app/models/user.rb', ':registerable,', ' :lockable,'
168
269
  if mongoid
169
270
  gsub_file 'app/models/user.rb', '# field :failed_attempts', 'field :failed_attempts'
@@ -181,16 +282,16 @@ inject_into_file 'app/models/user.rb', before: /^end/ do <<-TEXT
181
282
  self.roles.reject! { |r| r.blank? }
182
283
  end
183
284
 
184
- AVAILABLE_ROLES = ["admin", "manager", "client"]
285
+ AVAILABLE_ROLES = ["admin", "manager", "client"].freeze
185
286
 
186
287
  AVAILABLE_ROLES.each do |r|
187
- class_eval <<-EVAL
288
+ class_eval <<-RUBY
188
289
  def \#{r}?
189
290
  self.roles and self.roles.include?("\#{r}")
190
291
  end
191
292
 
192
293
  scope :\#{r.pluralize}, -> { any_in(roles: "\#{r}") }
193
- EVAL
294
+ RUBY
194
295
  end
195
296
 
196
297
  def self.generate_first_admin_user
@@ -224,6 +325,7 @@ inject_into_file 'app/models/user.rb', before: /^end/ do <<-TEXT
224
325
  end
225
326
 
226
327
  rails_admin do
328
+ navigation_icon 'icon-user'
227
329
  list do
228
330
  field :email
229
331
  field :name
@@ -256,9 +358,9 @@ inject_into_file 'app/models/user.rb', before: /^end/ do <<-TEXT
256
358
 
257
359
  group :roles do
258
360
  active false
259
- field :roles, :enum do
361
+ field :roles, :hancock_enum do
260
362
  enum do
261
- AVAILABLE_ROLES
363
+ ::User::AVAILABLE_ROLES
262
364
  end
263
365
 
264
366
  multiple do
@@ -293,6 +395,8 @@ inject_into_file 'app/models/user.rb', before: /^end/ do <<-TEXT
293
395
  TEXT
294
396
  end
295
397
  end
398
+ end
399
+ end
296
400
 
297
401
 
298
402
  ###### HANCOCK OTHERS ######
@@ -302,26 +406,32 @@ generate "hancock:cms:migration"
302
406
  generate "rails_admin_settings:migration"
303
407
  end
304
408
 
409
+ if ["yes", "y"].include?(ask_with_timeout("Set Hancock's layout? (y or yes)").downcase.strip)
305
410
  remove_file 'app/views/layouts/application.html.erb'
306
411
  generate "hancock:cms:layout"
307
-
308
- unless mongoid
309
- rake "db:migrate"
310
412
  end
311
413
 
312
414
  run 'rails r "User.generate_first_admin_user"'
313
415
 
416
+ if ["yes", "y"].include?(ask_with_timeout("Set Hancock's assets? (y or yes)").downcase.strip)
314
417
  remove_file 'app/assets/stylesheets/application.css'
315
418
  remove_file 'app/assets/javascripts/application.js'
316
419
  generate "hancock:cms:assets", app_name
420
+ end
317
421
 
422
+ if ["yes", "y"].include?(ask_with_timeout("Set Hancock's robots.txt? (y or yes)").downcase.strip)
318
423
  remove_file 'public/robots.txt'
319
424
  generate "hancock:cms:robots", app_name
425
+ end
320
426
 
427
+ if ["yes", "y"].include?(ask_with_timeout("Set Hancock's unicorn config? (y or yes)").downcase.strip)
321
428
  #god+unicorn
322
429
  generate "hancock:cms:unicorn_god", app_name
430
+ end
431
+ if ["yes", "y"].include?(ask_with_timeout("Set Hancock's scripts? (y or yes)").downcase.strip)
323
432
  #scripts
324
433
  generate "hancock:cms:scripts", app_name
434
+ end
325
435
 
326
436
  FileUtils.cp(Pathname.new(destination_root).join('config', 'secrets.yml').to_s, Pathname.new(destination_root).join('config', 'secrets.yml.example').to_s)
327
437
 
@@ -331,7 +441,7 @@ generate "friendly_id"
331
441
  rake "db:migrate"
332
442
  end
333
443
 
334
- generate "rspec:install"
444
+ generate "rspec:install" if ["yes", "y"].include?(ask_with_timeout("generate `rspec:install`? (y or yes)").downcase.strip)
335
445
 
336
446
 
337
447
  ####### GIT #######
@@ -350,16 +460,19 @@ create_file '.gitignore' do <<-TEXT
350
460
  /log/*.log
351
461
  /tmp/*
352
462
  /public/assets
353
- /public/ckeditor_assets
463
+ # /public/ckeditor_assets
354
464
  Gemfile.lock
355
465
  TEXT
356
466
  end
357
467
 
358
468
  create_file 'extra/.gitkeep', ''
359
469
 
470
+
471
+ if ["yes", "y"].include?(ask_with_timeout("Do u want init git? (y or yes)").downcase.strip)
360
472
  git :init
361
473
  git add: "."
362
474
  git commit: %Q{ -m 'Initial commit' }
475
+ end
363
476
 
364
477
  end
365
478