spina 0.11.1 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of spina might be problematic. Click here for more details.

Files changed (131) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +41 -12
  3. data/Rakefile +1 -0
  4. data/app/assets/fonts/spina/ics_spina.eot +0 -0
  5. data/app/assets/fonts/spina/ics_spina.svg +5 -3
  6. data/app/assets/fonts/spina/ics_spina.ttf +0 -0
  7. data/app/assets/fonts/spina/ics_spina.woff +0 -0
  8. data/app/assets/icons/spina/lock.svg +3 -0
  9. data/app/assets/icons/spina/preview/ics_spina-preview.html +16 -1
  10. data/app/assets/javascripts/spina/admin/application.coffee.erb +3 -25
  11. data/app/assets/javascripts/spina/admin/navigation.coffee +7 -0
  12. data/app/assets/javascripts/spina/admin/pages.coffee.erb +1 -13
  13. data/app/assets/javascripts/spina/admin/trix.coffee.erb +2 -1
  14. data/app/assets/stylesheets/spina/_admin_editing.sass +0 -4
  15. data/app/assets/stylesheets/spina/_buttons.sass +8 -8
  16. data/app/assets/stylesheets/spina/_configuration.sass +5 -1
  17. data/app/assets/stylesheets/spina/_custom_animations.sass +26 -26
  18. data/app/assets/stylesheets/spina/_fonts.sass +5 -1
  19. data/app/assets/stylesheets/spina/_forms.sass +66 -33
  20. data/app/assets/stylesheets/spina/_gallery.sass +32 -15
  21. data/app/assets/stylesheets/spina/_ics_spina.scss +1 -0
  22. data/app/assets/stylesheets/spina/_login.sass +10 -4
  23. data/app/assets/stylesheets/spina/_mixins.sass +5 -0
  24. data/app/assets/stylesheets/spina/_modal.sass +4 -4
  25. data/app/assets/stylesheets/spina/_notifications.sass +5 -5
  26. data/app/assets/stylesheets/spina/_sortable_lists.sass +9 -9
  27. data/app/assets/stylesheets/spina/_tables.sass +9 -9
  28. data/app/assets/stylesheets/spina/_wizard.sass +5 -5
  29. data/app/assets/stylesheets/spina/admin/application.sass +4 -1
  30. data/app/assets/stylesheets/spina/application.sass +0 -1
  31. data/app/assets/stylesheets/spina.sass +23 -27
  32. data/app/controllers/spina/admin/accounts_controller.rb +2 -7
  33. data/app/controllers/spina/admin/admin_controller.rb +8 -3
  34. data/app/controllers/spina/admin/attachments_controller.rb +0 -2
  35. data/app/controllers/spina/admin/navigations_controller.rb +3 -2
  36. data/app/controllers/spina/admin/pages_controller.rb +7 -8
  37. data/app/controllers/spina/admin/password_resets_controller.rb +49 -0
  38. data/app/controllers/spina/admin/photos_controller.rb +15 -34
  39. data/app/controllers/spina/admin/sessions_controller.rb +1 -1
  40. data/app/controllers/spina/admin/users_controller.rb +8 -9
  41. data/app/controllers/spina/application_controller.rb +3 -9
  42. data/app/controllers/spina/pages_controller.rb +3 -3
  43. data/app/helpers/spina/admin/pages_helper.rb +16 -23
  44. data/app/mailers/spina/user_mailer.rb +21 -0
  45. data/app/models/concerns/spina/optionable.rb +12 -0
  46. data/app/models/concerns/spina/part.rb +5 -1
  47. data/app/models/concerns/spina/partable.rb +20 -5
  48. data/app/models/concerns/spina/photo_collectable.rb +24 -0
  49. data/app/models/spina/account.rb +16 -6
  50. data/app/models/spina/layout_part.rb +1 -0
  51. data/app/models/spina/option.rb +17 -0
  52. data/app/models/spina/page.rb +36 -63
  53. data/app/models/spina/page_part.rb +1 -0
  54. data/app/models/spina/photo_collection.rb +1 -13
  55. data/app/models/spina/structure_item.rb +4 -8
  56. data/app/models/spina/structure_part.rb +2 -13
  57. data/app/models/spina/user.rb +1 -0
  58. data/app/presenters/spina/pages/menu_presenter.rb +18 -49
  59. data/app/views/layouts/spina/mail.html.erb +1 -0
  60. data/app/views/spina/admin/page_partables/{colors → options}/_form.html.haml +2 -3
  61. data/app/views/spina/admin/page_partables/photo_collections/_form.html.haml +7 -7
  62. data/app/views/spina/admin/page_partables/structures/_form.html.haml +7 -8
  63. data/app/views/spina/admin/pages/_form.html.haml +2 -2
  64. data/app/views/spina/admin/pages/_form_advanced.html.haml +2 -2
  65. data/app/views/spina/admin/password_resets/edit.html.haml +13 -0
  66. data/app/views/spina/admin/password_resets/new.html.haml +13 -0
  67. data/app/views/spina/admin/photos/_photo.html.haml +2 -1
  68. data/app/views/spina/admin/photos/{_wysihtml5_select.html.haml → _trix_select.html.haml} +2 -4
  69. data/app/views/spina/admin/photos/create.js.erb +3 -5
  70. data/app/views/spina/admin/photos/{wysihtml5_infinite_scroll.js.erb → trix_infinite_scroll.js.erb} +0 -2
  71. data/app/views/spina/admin/photos/{wysihtml5_insert.js.coffee → trix_insert.js.erb} +2 -2
  72. data/app/views/spina/admin/photos/trix_select.js.erb +3 -0
  73. data/app/views/spina/admin/sessions/new.html.haml +3 -1
  74. data/app/views/spina/admin/shared/_primary_navigation.html.haml +1 -1
  75. data/app/views/spina/admin/shared/_rich_text_field.html.haml +2 -1
  76. data/app/views/spina/admin/structure_items/_fields.html.haml +3 -3
  77. data/app/views/spina/admin/structure_partables/lines/_form.html.haml +5 -2
  78. data/app/views/spina/admin/structure_partables/options/_form.html.haml +7 -0
  79. data/app/views/spina/admin/structure_partables/photo_collections/_form.html.haml +12 -9
  80. data/app/views/spina/admin/structure_partables/photos/_form.html.haml +10 -7
  81. data/app/views/spina/admin/structure_partables/texts/_form.html.haml +5 -2
  82. data/app/views/spina/admin/users/_form.html.haml +1 -1
  83. data/app/views/spina/shared/_admin_bar.html.haml +1 -1
  84. data/app/views/spina/shared/_navigation.html.haml +1 -1
  85. data/app/views/spina/user_mailer/forgot_password.html.erb +1 -0
  86. data/app/views/spina/user_mailer/forgot_password.txt.erb +1 -0
  87. data/config/locales/en.yml +10 -0
  88. data/config/locales/nl.yml +2 -0
  89. data/config/routes.rb +5 -9
  90. data/db/migrate/1_create_spina_tables.rb +8 -7
  91. data/db/migrate/2_create_spina_translation_tables.rb +7 -26
  92. data/db/migrate/3_create_spina_navigations.rb +1 -1
  93. data/db/migrate/4_add_password_reset_token_to_spina_users.rb +6 -0
  94. data/db/migrate/5_remove_translated_columns.rb +11 -0
  95. data/db/migrate/6_create_spina_options.rb +8 -0
  96. data/lib/generators/spina/install_generator.rb +0 -22
  97. data/lib/generators/spina/templates/app/views/default/shared/_navigation.html.haml +1 -1
  98. data/lib/generators/spina/templates/app/views/demo/shared/_navigation.html.haml +1 -1
  99. data/lib/generators/spina/templates/config/initializers/themes/default.rb +9 -0
  100. data/lib/generators/spina/templates/config/initializers/themes/demo.rb +1 -9
  101. data/lib/spina/engine.rb +4 -3
  102. data/lib/spina/theme.rb +2 -1
  103. data/lib/spina/version.rb +1 -1
  104. data/lib/spina.rb +0 -23
  105. metadata +32 -69
  106. data/app/assets/images/spina/marker.png +0 -0
  107. data/app/assets/images/spina/mask.png +0 -0
  108. data/app/assets/images/spina/wheel.png +0 -0
  109. data/app/assets/stylesheets/spina/_cards.sass +0 -54
  110. data/app/assets/stylesheets/spina/_farbtastic.sass +0 -37
  111. data/app/assets/stylesheets/spina/_wysihtml5.sass +0 -79
  112. data/app/assets/stylesheets/spina/wysihtml5_textarea.sass +0 -14
  113. data/app/controllers/spina/admin/page_parts_controller.rb +0 -11
  114. data/app/helpers/spina/application_helper.rb +0 -30
  115. data/app/models/spina/ability.rb +0 -20
  116. data/app/models/spina/color.rb +0 -7
  117. data/app/presenters/spina/pages/breadcrumb.rb +0 -102
  118. data/app/views/layouts/spina/email.html.erb +0 -124
  119. data/app/views/spina/admin/layout_partables/colors/_form.html.haml +0 -4
  120. data/app/views/spina/admin/page_parts/_wysihtml5_link.html.haml +0 -12
  121. data/app/views/spina/admin/page_parts/insert_wysihtml5_link.js +0 -5
  122. data/app/views/spina/admin/page_parts/wysihtml5_link.js +0 -2
  123. data/app/views/spina/admin/photos/create_and_select.js.erb +0 -7
  124. data/app/views/spina/admin/photos/create_multiple.js.erb +0 -4
  125. data/app/views/spina/admin/photos/wysihtml5_select.js.erb +0 -3
  126. data/vendor/assets/javascripts/spina/jquery.farbtastic.js +0 -345
  127. data/vendor/assets/javascripts/spina/morris.js +0 -1767
  128. data/vendor/assets/javascripts/spina/raphael.js +0 -8111
  129. data/vendor/assets/javascripts/spina/wysihtml5.js +0 -269
  130. data/vendor/assets/javascripts/spina/wysihtml5_parser_rules.js +0 -551
  131. data/vendor/assets/stylesheets/spina/_morris.scss +0 -2
@@ -1,9 +1,24 @@
1
1
  module Spina
2
2
  module Partable
3
- def part(part)
4
- part = parts.where(name: part[:name]).first || parts.build(part)
5
- part.partable = part.partable_type.constantize.new unless part.partable.present?
6
- part
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ def part(attributes)
7
+ part = parts.where(name: attributes[:name]).first_or_initialize(attributes)
8
+ part.partable = part.partable_type.constantize.new if part.partable.blank?
9
+ part.options = attributes[:options]
10
+ part
11
+ end
12
+
13
+ def has_content?(name)
14
+ content(name).present?
15
+ end
16
+
17
+ def content(name)
18
+ part = parts.find_by(name: name)
19
+ part.try(:content)
20
+ end
21
+
7
22
  end
8
23
  end
9
- end
24
+ end
@@ -0,0 +1,24 @@
1
+ require 'active_support/concern'
2
+
3
+ module Spina
4
+ module PhotoCollectable
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ attr_reader :photo_tokens, :photo_positions
9
+ end
10
+
11
+ def photo_tokens=(ids)
12
+ self.photo_ids = ids.split(",")
13
+ end
14
+
15
+ def photo_positions=(positions)
16
+ positions = positions.split(",")
17
+ self.photo_collections_photos.each do |photo|
18
+ photo.position = positions.index(photo.photo.try(:id).try(:to_s))
19
+ end
20
+ logger.info self.photo_collections_photos.inspect
21
+ end
22
+
23
+ end
24
+ end
@@ -1,7 +1,8 @@
1
1
  module Spina
2
2
  class Account < ApplicationRecord
3
+ include Partable
4
+
3
5
  serialize :preferences
4
- include Spina::Partable
5
6
 
6
7
  mount_uploader :logo, LogoUploader
7
8
 
@@ -42,7 +43,10 @@ module Spina
42
43
 
43
44
  def bootstrap_website
44
45
  theme_config = ::Spina::Theme.find_by_name(theme)
45
- bootstrap_pages(theme_config) if theme_config
46
+ if theme_config
47
+ bootstrap_pages(theme_config)
48
+ bootstrap_navigations(theme_config)
49
+ end
46
50
  end
47
51
 
48
52
  def bootstrap_pages(theme)
@@ -51,20 +55,26 @@ module Spina
51
55
  activate_used_view_templates(theme)
52
56
  end
53
57
 
58
+ def bootstrap_navigations(theme)
59
+ theme.navigations.each_with_index do |navigation, index|
60
+ Navigation.where(name: navigation[:name]).first_or_create.update_attributes(navigation.merge(position: index))
61
+ end
62
+ end
63
+
54
64
  def find_or_create_custom_pages(theme)
55
65
  theme.custom_pages.each do |page|
56
- Page.by_name(page[:name])
66
+ Page.where(name: page[:name])
57
67
  .first_or_create(title: page[:title])
58
- .update_columns(view_template: page[:view_template], deletable: page[:deletable])
68
+ .update_attributes(view_template: page[:view_template], deletable: page[:deletable])
59
69
  end
60
70
  end
61
71
 
62
72
  def deactivate_unused_view_templates(theme)
63
- Page.active.not_by_config_theme(theme).update_all(active: false)
73
+ Page.active.where.not(view_template: theme.view_templates.map{|h|h[:name]}).update_all(active: false)
64
74
  end
65
75
 
66
76
  def activate_used_view_templates(theme)
67
- Page.not_active.by_config_theme(theme).update_all(active: true)
77
+ Page.where(active: false, view_template: theme.view_templates.map{|h|h[:name]}).update_all(active: true)
68
78
  end
69
79
 
70
80
  end
@@ -1,6 +1,7 @@
1
1
  module Spina
2
2
  class LayoutPart < ApplicationRecord
3
3
  include Part
4
+ include Optionable
4
5
 
5
6
  belongs_to :account
6
7
  belongs_to :layout_partable, polymorphic: true
@@ -0,0 +1,17 @@
1
+ module Spina
2
+ class Option < ApplicationRecord
3
+ has_one :page_part, as: :page_partable
4
+ has_one :layout_part, as: :layout_partable
5
+ has_one :structure_part, as: :structure_partable
6
+
7
+ def content
8
+ I18n.t(['options',part.name,value].compact.join('.'))
9
+ end
10
+
11
+ private
12
+
13
+ def part
14
+ page_part || layout_part || structure_part
15
+ end
16
+ end
17
+ end
@@ -1,40 +1,38 @@
1
1
  module Spina
2
2
  class Page < ApplicationRecord
3
- include Spina::Partable
4
-
5
- translates :title, :menu_title, :seo_title, :description, :materialized_path
3
+ include Partable
6
4
 
5
+ # Stores the old path when generating a new materialized_path
7
6
  attr_accessor :old_path
8
7
 
9
- has_ancestry orphan_strategy: :adopt # i.e. added to the parent of deleted node
10
-
8
+ # Page contains multiple parts called PageParts
11
9
  has_many :page_parts, dependent: :destroy, inverse_of: :page
10
+ alias_attribute :parts, :page_parts
11
+ accepts_nested_attributes_for :page_parts, allow_destroy: true
12
+
13
+ # Orphaned pages are adopted by parent pages if available, otherwise become root
14
+ has_ancestry orphan_strategy: :adopt
15
+
16
+ # Pages can belong to navigations (optional)
12
17
  has_many :navigation_items, dependent: :destroy
13
18
  has_many :navigations, through: :navigation_items
14
19
 
15
- before_validation :ensure_title
16
- before_validation :ancestry_is_nil
17
- before_validation :set_materialized_path
20
+ scope :active, -> { where(active: true) }
21
+ scope :sorted, -> { order(:position) }
22
+ scope :live, -> { active.where(draft: false) }
23
+ scope :in_menu, -> { where(show_in_menu: true) }
24
+
25
+ # Save children to update all materialized_paths
18
26
  after_save :save_children
27
+
28
+ # Create a 301 redirect if materialized_path changed
19
29
  after_save :rewrite_rule
20
- after_create :add_to_navigation
21
30
 
22
- accepts_nested_attributes_for :page_parts, allow_destroy: true
23
- validates_presence_of :title
31
+ before_validation :set_materialized_path
32
+ validates :title, presence: true
24
33
  validates :materialized_path, uniqueness: true
25
34
 
26
- scope :sorted, -> { order('position') }
27
- scope :custom_pages, -> { where(deletable: false) }
28
- scope :live, -> { where(draft: false, active: true) }
29
- scope :in_menu, -> { where(show_in_menu: true) }
30
- scope :active, -> { where(active: true) }
31
- scope :not_active, -> { where(active: false) }
32
- scope :by_name, ->(name) { where(name: name) }
33
- scope :not_by_config_theme, ->(theme) { where.not(view_template: theme.view_templates.map { |h| h[:name] }) }
34
- scope :by_config_theme, ->(theme) { where(view_template: theme.view_templates.map { |h| h[:name] }) }
35
-
36
- alias_attribute :page_part, :part
37
- alias_attribute :parts, :page_parts
35
+ translates :title, :menu_title, :seo_title, :description, :materialized_path
38
36
 
39
37
  def to_s
40
38
  name
@@ -60,15 +58,6 @@ module Spina
60
58
  read_attribute(:seo_title).blank? ? title : read_attribute(:seo_title)
61
59
  end
62
60
 
63
- def has_content?(page_part)
64
- content(page_part).present?
65
- end
66
-
67
- def content(page_part)
68
- page_part = page_parts.where(name: page_part).first
69
- page_part.try(:content)
70
- end
71
-
72
61
  def live?
73
62
  !draft? && active?
74
63
  end
@@ -101,43 +90,27 @@ module Spina
101
90
  theme.page_parts.select { |page_part| page_part[:name].in? view_template_config(theme)[:page_parts] }
102
91
  end
103
92
 
104
- def full_materialized_path
105
- File.join(Spina::Engine.routes.url_helpers.root_path, materialized_path)
106
- end
107
-
108
93
  private
109
94
 
110
- def rewrite_rule
111
- RewriteRule.create(old_path: old_path, new_path: materialized_path) if old_path != materialized_path
112
- end
113
-
114
- def localized_materialized_path
115
- if I18n.locale == I18n.default_locale
116
- generate_materialized_path.prepend('/')
117
- else
118
- generate_materialized_path.prepend("/#{I18n.locale}/")
95
+ def rewrite_rule
96
+ RewriteRule.create(old_path: old_path, new_path: materialized_path) if old_path != materialized_path
119
97
  end
120
- end
121
98
 
122
- def generate_materialized_path
123
- if root?
124
- name == 'homepage' ? '' : "#{url_title}"
125
- else
126
- ancestors.collect(&:url_title).append(url_title).join('/')
99
+ def localized_materialized_path
100
+ if I18n.locale == I18n.default_locale
101
+ generate_materialized_path.prepend('/')
102
+ else
103
+ generate_materialized_path.prepend("/#{I18n.locale}/").gsub(/\/\z/, "")
104
+ end
127
105
  end
128
- end
129
-
130
- def ancestry_is_nil
131
- self.ancestry = self.ancestry.presence
132
- end
133
106
 
134
- def ensure_title
135
- self.title = self.name.capitalize if self.title.blank? && self.name.present?
136
- end
137
-
138
- def add_to_navigation
139
- navigations << Spina::Navigation.where(auto_add_pages: true)
140
- end
107
+ def generate_materialized_path
108
+ if root?
109
+ name == 'homepage' ? '' : "#{url_title}"
110
+ else
111
+ ancestors.collect(&:url_title).append(url_title).join('/')
112
+ end
113
+ end
141
114
 
142
115
  end
143
116
  end
@@ -1,6 +1,7 @@
1
1
  module Spina
2
2
  class PagePart < ApplicationRecord
3
3
  include Part
4
+ include Optionable
4
5
 
5
6
  belongs_to :page, inverse_of: :page_parts
6
7
  belongs_to :page_partable, polymorphic: true, optional: true
@@ -1,30 +1,18 @@
1
1
  module Spina
2
2
  class PhotoCollection < ApplicationRecord
3
+ include PhotoCollectable
3
4
 
4
5
  has_one :page_part, as: :page_partable
5
6
  has_many :photo_collections_photos, autosave: true
6
7
  has_many :photos, through: :photo_collections_photos
7
8
  has_many :structure_parts, as: :structure_partable
8
9
 
9
- attr_reader :photo_tokens, :photo_positions
10
10
  accepts_nested_attributes_for :photos, allow_destroy: true
11
11
 
12
12
  def content
13
13
  self
14
14
  end
15
15
 
16
- def photo_tokens=(ids)
17
- self.photo_ids = ids.split(",")
18
- end
19
-
20
- def photo_positions=(positions)
21
- positions = positions.split(",")
22
- self.photo_collections_photos.each do |photo|
23
- photo.position = positions.index(photo.photo.try(:id).try(:to_s))
24
- end
25
- logger.info self.photo_collections_photos.inspect
26
- end
27
-
28
16
  alias_method :old_update_attributes, :update_attributes
29
17
  def update_attributes(attributes)
30
18
  self.photos.clear if attributes.reject{|key,value| key == "id" }.blank?
@@ -1,21 +1,17 @@
1
1
  module Spina
2
2
  class StructureItem < ApplicationRecord
3
+ include Partable
4
+
3
5
  before_validation :ensure_position
4
6
  belongs_to :structure, optional: true
5
7
  has_many :structure_parts, dependent: :destroy
6
8
 
7
- scope :sorted_by_structure, -> { order('position') }
9
+ scope :sorted_by_structure, -> { order(:position) }
8
10
 
9
11
  validates_presence_of :position
10
12
  accepts_nested_attributes_for :structure_parts, allow_destroy: true
11
13
 
12
- def has_content?(structure_part)
13
- content(structure_part).present?
14
- end
15
-
16
- def content(structure_part)
17
- structure_parts.find_by(name: structure_part).try(:content)
18
- end
14
+ alias_attribute :parts, :structure_parts
19
15
 
20
16
  def ensure_position
21
17
  self.position ||= Time.now.to_i
@@ -1,6 +1,8 @@
1
1
  module Spina
2
2
  class StructurePart < ApplicationRecord
3
3
  include Part
4
+ include PhotoCollectable
5
+ include Optionable
4
6
 
5
7
  belongs_to :structure_item, optional: true
6
8
  belongs_to :structure_partable, polymorphic: true, optional: true
@@ -13,18 +15,5 @@ module Spina
13
15
  alias_attribute :partable, :structure_partable
14
16
  alias_attribute :partable_type, :structure_partable_type
15
17
  alias_method :structure_partable_attributes=, :partable_attributes=
16
-
17
- attr_reader :photo_tokens, :photo_positions
18
- def photo_tokens=(ids)
19
- self.photo_ids = ids.split(",")
20
- end
21
-
22
- def photo_positions=(positions)
23
- positions = positions.split(",")
24
- self.photo_collections_photos.each do |photo|
25
- photo.position = positions.index(photo.photo.try(:id).try(:to_s))
26
- end
27
- logger.info self.photo_collections_photos.inspect
28
- end
29
18
  end
30
19
  end
@@ -1,6 +1,7 @@
1
1
  module Spina
2
2
  class User < ApplicationRecord
3
3
  has_secure_password
4
+ has_secure_token :password_reset_token
4
5
 
5
6
  validates_presence_of :name, :email
6
7
  validates_presence_of :password, on: :create
@@ -1,4 +1,3 @@
1
- # require 'active_support/core_ext/string'
2
1
  require 'active_support/configurable'
3
2
  require 'action_view/helpers/tag_helper'
4
3
  require 'action_view/helpers/url_helper'
@@ -10,24 +9,19 @@ module Spina
10
9
  include ActionView::Helpers::UrlHelper
11
10
  include ActiveSupport::Configurable
12
11
 
13
- config_accessor :list_tag, :list_class, :li, :list_wrapper, :list_item_tag, :list_item_css, :selected_css, :current_css, :first_css, :last_css, :list_tag_with_child_css, :list_item_with_child_css
12
+ config_accessor :list_tag, :list_class, :list_item_tag, :list_item_css, :selected_css, :current_css
14
13
 
15
14
  self.list_tag = :ul
16
15
  self.list_class = 'nav'
17
16
  self.list_item_tag = :li
18
17
  self.list_item_css = nil
19
- self.list_wrapper = false
20
18
  self.selected_css = 'active'
21
19
  self.current_css = 'current'
22
- self.first_css = 'first'
23
- self.last_css = 'last'
24
- self.list_tag_with_child_css = 'dropdown-menu'
25
- self.list_item_with_child_css = 'dropdown'
26
20
 
27
21
  attr_accessor :context, :collection, :current_menu_item
28
22
  delegate :output_buffer, :output_buffer=, to: :context
29
23
 
30
- def initialize(collection, context, current_menu_item=nil)
24
+ def initialize(collection, context, current_menu_item = nil)
31
25
  @collection = collection
32
26
  @context = context
33
27
  @current_menu_item = current_menu_item
@@ -35,59 +29,34 @@ module Spina
35
29
  end
36
30
 
37
31
  def to_html
38
- render_list_wrapper(collection) if collection.present?
32
+ render_menu_items(collection) if collection.present?
39
33
  end
40
34
 
41
35
  private
42
36
 
43
- def render_list_wrapper(menu_items)
44
- if menu_items.any?
45
- if list_wrapper
46
- content_tag(:div) do
47
- render_menu_items(menu_items)
37
+ def render_menu_items(menu_items)
38
+ content_tag(list_tag, class: list_class) do
39
+ menu_items.each.inject(ActiveSupport::SafeBuffer.new) do |buffer, item|
40
+ buffer << render_menu_item(item)
48
41
  end
49
- else
50
- render_menu_items(menu_items)
51
42
  end
52
43
  end
53
- end
54
44
 
55
- def render_menu_items(menu_items)
56
- content_tag(list_tag, class: menu_items_css(menu_items)) do
57
- menu_items.each_with_index.inject(ActiveSupport::SafeBuffer.new) do |buffer, (item, index)|
58
- buffer << render_menu_item(item, index, menu_items.length)
45
+ def render_menu_item(menu_item)
46
+ content_tag(list_item_tag, class: menu_item_css(menu_item[0])) do
47
+ buffer = ActiveSupport::SafeBuffer.new
48
+ buffer << link_to(menu_item[0].menu_title, menu_item[0].materialized_path)
49
+ buffer << render_menu_items(menu_item[1]) if menu_item[1].present?
50
+ buffer
59
51
  end
60
52
  end
61
- end
62
53
 
63
- def render_menu_item(menu_item, index, menu_items_length)
64
- content_tag(list_item_tag, class: menu_item_css(menu_item[0], index, menu_items_length, !menu_item[1].empty?)) do
65
- buffer = ActiveSupport::SafeBuffer.new
66
- buffer << link_to(menu_item[0].menu_title, menu_item[0].full_materialized_path)
67
- buffer << render_list_wrapper(menu_item[1])
68
- buffer
54
+ def menu_item_css(menu_item)
55
+ css = [list_item_css]
56
+ css << selected_css if (@selected_menu_items.present? && @selected_menu_items.include?(menu_item) )
57
+ css << current_css if @current_menu_item == menu_item
58
+ css
69
59
  end
70
- end
71
-
72
- def menu_items_css(menu_items)
73
- css = []
74
- css << list_class
75
- css << list_tag_with_child_css if !menu_items.first[0].ancestry.nil?
76
-
77
- css.reject(&:blank?).presence
78
- end
79
-
80
- def menu_item_css(menu_item, index, menu_items_length, has_child)
81
- css = []
82
- css << list_item_css
83
- css << selected_css if (@selected_menu_items.present? && @selected_menu_items.include?(menu_item) )
84
- css << current_css if @current_menu_item == menu_item
85
- css << first_css if index == 0
86
- css << last_css if index + 1 == menu_items_length
87
- css << list_item_with_child_css if has_child
88
-
89
- css.reject(&:blank?).presence
90
- end
91
60
 
92
61
  end
93
62
  end
@@ -0,0 +1 @@
1
+ <%= yield %>
@@ -2,6 +2,5 @@
2
2
  = f.object.title
3
3
  .horizontal-form-content
4
4
  = f.fields_for :page_partable, f.object.page_partable do |ff|
5
- .colorpicker
6
- = ff.text_field :content, placeholder: f.object.title
7
- .colorpicker-container
5
+ .select-dropdown
6
+ = ff.select :value, f.object.options[:values].map{|o| [option_label(f.object, o), o]}, prompt: true
@@ -8,10 +8,10 @@
8
8
  %i.icon.icon-dots
9
9
  =t 'spina.pages.photos_picker'
10
10
 
11
- .photo-collection
12
- - if ff.object.photos.sorted_by_photo_collection.any?
13
- = render 'spina/admin/photos/photo_collection', photos: ff.object.photos.sorted_by_photo_collection
14
- - elsif ff.object.photos.any?
15
- = render 'spina/admin/photos/photo_collection', photos: ff.object.photos
16
- = ff.hidden_field :photo_tokens, value: ff.object.photo_ids.join(",")
17
- = ff.hidden_field :photo_positions, value: ff.object.photos.sorted_by_photo_collection.pluck(:photo_id).join(","), class: 'photo-positions'
11
+ .photo-collection
12
+ - if ff.object.photos.sorted_by_photo_collection.any?
13
+ = render 'spina/admin/photos/photo_collection', photos: ff.object.photos.sorted_by_photo_collection
14
+ - elsif ff.object.photos.any?
15
+ = render 'spina/admin/photos/photo_collection', photos: ff.object.photos
16
+ = ff.hidden_field :photo_tokens, value: ff.object.photo_ids.join(",")
17
+ = ff.hidden_field :photo_positions, value: ff.object.photos.sorted_by_photo_collection.pluck(:photo_id).join(","), class: 'photo-positions'
@@ -4,19 +4,18 @@
4
4
  %label= f.object.title
5
5
 
6
6
  %ul
7
- - unless f.object.page_partable.nil?
8
- - f.object.page_partable.structure_items.sorted_by_structure.each_with_index do |structure_item, index|
9
- %li{class: ('active' if index == 0), data: {structure_item_id: structure_item.id}}
10
- = link_to "#structure_form_pane_#{structure_item.id}" do
11
- %i.icon.icon-bars.sortable-handle
12
- = structure_item.structure_parts.first.try(:structure_partable).try(:content)
7
+ - f.object.page_partable.structure_items.sort_by(&:position).each_with_index do |structure_item, index|
8
+ %li{class: ('active' if index == 0), data: {structure_item_id: structure_item.object_id}}
9
+ = link_to "#structure_form_pane_#{structure_item.object_id}" do
10
+ %i.icon.icon-bars.sortable-handle
11
+ = structure_item.structure_parts.first.try(:structure_partable).try(:content)
13
12
 
14
13
  = f.fields_for :page_partable do |ff|
15
14
  - ff.object.page_part = f.object
16
- = link_to_add_structure_item_fields ff, :structure_items do
15
+ = link_to_add_structure_item_fields ff do
17
16
  = icon('plus')
18
17
 
19
18
  .structure-form-content
20
19
  = f.fields_for :page_partable do |ff|
21
- = ff.fields_for :structure_items, ff.object.structure_items.sorted_by_structure do |fff|
20
+ = ff.fields_for :structure_items, ff.object.structure_items.sort_by(&:position) do |fff|
22
21
  = render 'spina/admin/structure_items/fields', f: fff
@@ -8,12 +8,12 @@
8
8
  = link_to '#', data: {close_notification: true} do
9
9
  = icon('cross')
10
10
 
11
- = form_for [spina, :admin, @page], html: {id: 'page_form', autocomplete: "off", data: {remote: @page.persisted?}} do |f|
11
+ = form_for [spina, :admin, @page], html: {id: 'page_form', autocomplete: "off"} do |f|
12
12
  %header#header
13
13
  .breadcrumbs= render_breadcrumbs separator: '<div class="divider"></div>'
14
14
  - unless @page.new_record?
15
15
  - if Spina.config.locales.size > 1
16
- %div{style: 'display: inline-block; margin-left: 12px; top: -4px', data: {dropdown: true}}
16
+ %div{style: 'display: inline-block; margin-left: 12px; position: absolute', data: {dropdown: true}}
17
17
  = link_to '#', class: 'button button-link button-round button-small', data: {trigger: 'dropdown', target: '#locales'} do
18
18
  = icon('comment')
19
19
  = @locale.upcase
@@ -39,9 +39,9 @@
39
39
  - options = options_for_select(current_theme.view_templates.map { |template| [template[:title], template[:name], {'data-page-parts' => template[:page_parts]}] }, @page.view_template)
40
40
  = f.select :view_template, options
41
41
 
42
- .horizontal-form-group{style: ('display: none' if @page.custom_page?)}
42
+ .horizontal-form-group
43
43
  .horizontal-form-label
44
44
  = Spina::Page.human_attribute_name :ancestry
45
45
  .horizontal-form-content
46
46
  .select-dropdown.ancestry
47
- = f.select :parent_id, page_ancestry_options(f.object), include_blank: Spina::Page.human_attribute_name(:no_parent)
47
+ = f.select :parent_id, page_ancestry_options(f.object), include_blank: Spina::Page.human_attribute_name(:no_parent)
@@ -0,0 +1,13 @@
1
+ = form_for @user, url: spina.admin_password_reset_path(params[:id]), html: {id: "login_wrapper"} do |f|
2
+ = image_tag 'spina/admin/spina.png', class: 'animated fadeInDown'
3
+ - if @user.errors.any?
4
+ .failed-to-login.animated.fadeInDown
5
+ .icon.icon-cross
6
+ = @user.errors.full_messages.join('<br />').html_safe
7
+
8
+ .login-fields
9
+ = f.text_field :password, placeholder: Spina::User.human_attribute_name(:password), autofocus: true, class: "animated fadeInDown"
10
+
11
+ = f.text_field :password_confirmation, placeholder: Spina::User.human_attribute_name(:password_confirmation), class: "animated fadeInDown"
12
+
13
+ = f.button t('spina.forgot_password.save'), class: 'button button-primary animated fadeInDown'
@@ -0,0 +1,13 @@
1
+ = form_tag spina.admin_password_resets_path, method: :post, id: "login_wrapper" do
2
+ = image_tag 'spina/admin/spina.png'
3
+ - if flash[:alert].present?
4
+ .failed-to-login.animated.fadeInDown
5
+ .icon.icon-cross
6
+ = flash[:alert]
7
+
8
+ .login-fields
9
+ = text_field_tag :email, params[:email], placeholder: Spina::User.human_attribute_name(:email), autofocus: true
10
+
11
+ = button_tag t('spina.forgot_password.request'), class: 'button button-primary'
12
+
13
+ .login-extra-links= link_to t('spina.login'), spina.admin_login_path, class: 'button button-hollow button-block'
@@ -1,7 +1,8 @@
1
1
  .item
2
2
  .overlay
3
3
  = link_to spina.admin_photo_path(photo), method: :delete, class: 'icon-only delete-photo-link', data: {confirm: t('spina.photos.delete_confirmation')} do
4
- =t('spina.photos.delete')
4
+ = t('spina.photos.delete')
5
+ %span.photo-name= truncate(photo.name, length: 125)
5
6
  = radio_button_tag :photo_id, photo.id
6
7
  = check_box_tag 'photo_ids[]', photo.id
7
8
  = image_tag photo.file.thumb.url, id: "photo_#{photo.id}"
@@ -5,9 +5,7 @@
5
5
  = form_for [spina, :admin, @photo], html: {multipart: true} do |f|
6
6
  = f.label :file, t('spina.photos.upload_image')
7
7
  = f.file_field :files, multiple: true, data: {customfileinput: true}
8
-
9
- = form_tag spina.wysihtml5_insert_admin_photos_path(params[:object_id]), remote: true, class: 'gallery-prepend-image' do
8
+ = form_tag spina.trix_insert_admin_photos_path(params[:object_id]), remote: true, class: 'gallery-prepend-image' do
10
9
  .infinite-scroll
11
10
  = render partial: 'spina/admin/photos/photo_single_picker', collection: @photos
12
-
13
- .infinite-pagination= link_to_next_page @photos, 'Next', remote: true
11
+ .infinite-pagination= link_to_next_page @photos, 'Next', remote: true
@@ -1,6 +1,4 @@
1
- <% if @photo.new_record? %>
2
- alert("<%= I18n.t 'spina.photos.cannot_be_created' %> <%= j @photo.errors.full_messages.join(', ').html_safe %>");
3
- <% else %>
4
- $item = $("<%=j render partial: 'spina/admin/photos/photo', object: @photo %>");
1
+ <% @photos.each do |photo| %>
2
+ $item = $("<%=j render partial: 'spina/admin/photos/photo', object: photo %>");
5
3
  $(".gallery-prepend-image .infinite-scroll").prepend($item);
6
- <% end %>
4
+ <% end %>
@@ -1,6 +1,4 @@
1
1
  // Append new data
2
2
  $("<%=j render partial: 'spina/admin/photos/photo_single_picker', collection: @photos %>").appendTo($(".infinite-scroll"));
3
-
4
3
  // Update pagination link
5
4
  $('.infinite-pagination').html("<%= j link_to_next_page @photos, 'Next', remote: true %>").infiniteScroll()
6
-
@@ -1,2 +1,2 @@
1
- $('#<%= params[:object_id] %>').trigger('photo-insert', '<%= @photo.file.url %>')
2
- $.hideModal()
1
+ $('#<%= params[:object_id] %>').trigger('photo-insert', '<%= @photo.file.url %>')
2
+ $.hideModal()