decidim-proposals 0.18.1 → 0.19.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/decidim_proposals_manifest.js +0 -1
  3. data/app/assets/javascripts/decidim/proposals/admin/proposals_form.js.es6 +5 -0
  4. data/app/cells/decidim/proposals/collaborative_draft_m_cell.rb +1 -0
  5. data/app/cells/decidim/proposals/endorsers_list_cell.rb +1 -0
  6. data/app/cells/decidim/proposals/irreversible_action_modal_cell.rb +1 -0
  7. data/app/cells/decidim/proposals/participatory_text_proposal/buttons.erb +8 -8
  8. data/app/cells/decidim/proposals/participatory_text_proposal_cell.rb +13 -0
  9. data/app/cells/decidim/proposals/proposal_link_to_collaborative_draft_cell.rb +4 -8
  10. data/app/cells/decidim/proposals/{proposal_link_to_collaborative_draft → proposal_link_to_rejected_emendation}/show.erb +0 -0
  11. data/app/cells/decidim/proposals/proposal_link_to_rejected_emendation_cell.rb +34 -0
  12. data/app/cells/decidim/proposals/proposal_linked_resources/show.erb +9 -0
  13. data/app/cells/decidim/proposals/proposal_linked_resources_cell.rb +14 -0
  14. data/app/cells/decidim/proposals/proposal_m_cell.rb +3 -0
  15. data/app/commands/decidim/proposals/admin/create_proposal.rb +10 -33
  16. data/app/commands/decidim/proposals/admin/import_participatory_text.rb +2 -0
  17. data/app/commands/decidim/proposals/admin/merge_proposals.rb +1 -0
  18. data/app/commands/decidim/proposals/admin/publish_participatory_text.rb +24 -1
  19. data/app/commands/decidim/proposals/admin/update_participatory_text.rb +11 -7
  20. data/app/commands/decidim/proposals/admin/update_proposal.rb +9 -1
  21. data/app/commands/decidim/proposals/gallery_methods.rb +67 -0
  22. data/app/commands/decidim/proposals/unvote_proposal.rb +1 -0
  23. data/app/commands/decidim/proposals/update_proposal.rb +6 -1
  24. data/app/commands/decidim/proposals/vote_proposal.rb +1 -0
  25. data/app/controllers/concerns/decidim/proposals/collaborative_orderable.rb +1 -15
  26. data/app/controllers/concerns/decidim/proposals/orderable.rb +1 -15
  27. data/app/controllers/decidim/proposals/admin/participatory_texts_controller.rb +5 -0
  28. data/app/controllers/decidim/proposals/application_controller.rb +1 -0
  29. data/app/controllers/decidim/proposals/collaborative_drafts_controller.rb +1 -0
  30. data/app/controllers/decidim/proposals/proposal_endorsements_controller.rb +1 -1
  31. data/app/controllers/decidim/proposals/proposal_votes_controller.rb +1 -1
  32. data/app/controllers/decidim/proposals/proposals_controller.rb +22 -23
  33. data/app/forms/decidim/proposals/admin/proposal_form.rb +3 -0
  34. data/app/forms/decidim/proposals/admin/proposals_fork_form.rb +1 -0
  35. data/app/forms/decidim/proposals/proposal_wizard_create_step_form.rb +1 -0
  36. data/app/helpers/decidim/proposals/admin/proposals_helper.rb +1 -0
  37. data/app/helpers/decidim/proposals/map_helper.rb +1 -1
  38. data/app/helpers/decidim/proposals/proposal_cells_helper.rb +2 -0
  39. data/app/helpers/decidim/proposals/proposal_endorsements_helper.rb +1 -0
  40. data/app/helpers/decidim/proposals/proposal_votes_helper.rb +5 -0
  41. data/app/helpers/decidim/proposals/proposal_wizard_helper.rb +1 -0
  42. data/app/models/decidim/proposals/collaborative_draft.rb +1 -0
  43. data/app/models/decidim/proposals/proposal.rb +4 -8
  44. data/app/models/decidim/proposals/proposal_endorsement.rb +2 -0
  45. data/app/models/decidim/proposals/proposal_vote.rb +2 -0
  46. data/app/permissions/decidim/proposals/admin/permissions.rb +1 -0
  47. data/app/permissions/decidim/proposals/permissions.rb +17 -0
  48. data/app/presenters/decidim/proposals/admin_log/value_types/proposal_state_presenter.rb +1 -0
  49. data/app/presenters/decidim/proposals/collaborative_draft_presenter.rb +1 -1
  50. data/app/presenters/decidim/proposals/proposal_presenter.rb +4 -2
  51. data/app/queries/decidim/proposals/metrics/endorsements_metric_manage.rb +1 -0
  52. data/app/queries/decidim/proposals/metrics/proposal_followers_metric_measure.rb +2 -0
  53. data/app/queries/decidim/proposals/metrics/proposal_participants_metric_measure.rb +3 -0
  54. data/app/queries/decidim/proposals/metrics/proposals_metric_manage.rb +1 -0
  55. data/app/queries/decidim/proposals/metrics/votes_metric_manage.rb +1 -0
  56. data/app/services/decidim/proposals/diff_renderer.rb +43 -0
  57. data/app/services/decidim/proposals/proposal_builder.rb +23 -0
  58. data/app/services/decidim/proposals/proposal_search.rb +5 -3
  59. data/app/views/decidim/proposals/admin/proposals/_form.html.erb +24 -0
  60. data/app/views/decidim/proposals/admin/proposals/_proposal-tr.html.erb +3 -3
  61. data/app/views/decidim/proposals/collaborative_drafts/_collaborative_drafts.html.erb +1 -1
  62. data/app/views/decidim/proposals/collaborative_drafts/show.html.erb +0 -3
  63. data/app/views/decidim/proposals/proposal_endorsements/_identity.html.erb +1 -1
  64. data/app/views/decidim/proposals/proposals/_filters.html.erb +2 -1
  65. data/app/views/decidim/proposals/proposals/_proposal_preview.html.erb +1 -1
  66. data/app/views/decidim/proposals/proposals/_proposals.html.erb +1 -1
  67. data/app/views/decidim/proposals/proposals/index.html.erb +1 -1
  68. data/app/views/decidim/proposals/proposals/participatory_texts/_index.html.erb +1 -1
  69. data/app/views/decidim/proposals/proposals/show.html.erb +13 -9
  70. data/config/locales/ar.yml +2 -0
  71. data/config/locales/ca.yml +20 -0
  72. data/config/locales/cs.yml +20 -0
  73. data/config/locales/de.yml +2 -0
  74. data/config/locales/en.yml +20 -0
  75. data/config/locales/es-MX.yml +18 -0
  76. data/config/locales/es-PY.yml +18 -0
  77. data/config/locales/es.yml +20 -0
  78. data/config/locales/fi-plain.yml +20 -0
  79. data/config/locales/fi.yml +20 -0
  80. data/config/locales/fr.yml +21 -1
  81. data/config/locales/hu.yml +20 -0
  82. data/config/locales/it.yml +16 -0
  83. data/config/locales/nl.yml +20 -0
  84. data/config/locales/sv.yml +15 -0
  85. data/config/locales/tr-TR.yml +7 -0
  86. data/lib/decidim/content_parsers/proposal_parser.rb +2 -2
  87. data/lib/decidim/content_renderers/proposal_renderer.rb +1 -1
  88. data/lib/decidim/proposals/commentable_proposal.rb +1 -0
  89. data/lib/decidim/proposals/component.rb +8 -3
  90. data/lib/decidim/proposals/engine.rb +0 -1
  91. data/lib/decidim/proposals/markdown_to_proposals.rb +11 -7
  92. data/lib/decidim/proposals/proposal_serializer.rb +20 -2
  93. data/lib/decidim/proposals/version.rb +1 -1
  94. metadata +24 -38
  95. data/app/assets/config/decidim_proposals_manifest.css +0 -3
  96. data/app/assets/javascripts/decidim/proposals/social_share.js +0 -2
  97. data/app/assets/stylesheets/decidim/proposals/social_share.css.scss +0 -22
  98. data/config/initializers/social_share_button.rb +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 306966eaa2bcf8c8ffc812a513e1b388be7f32f436ad0a227259ca84bffc84aa
4
- data.tar.gz: 91791cb5717209c350d5ccd74a2d7bb49e5fe02c7e23d1ffde5ddfcc5eea0ca9
3
+ metadata.gz: 0e4a0b1c5edf206b2bf649405971a154486744d8946368b0454eca7936d51c47
4
+ data.tar.gz: 89554df3c8b7adcc5a3d9f694f5f08fbe59a6bd3a1e646d314ffc3b796425e46
5
5
  SHA512:
6
- metadata.gz: 576553bcf02a966a59848742b93262a0cbbb6a7e25eaa1c168b074d3341545ac9c3165a22b929b006fa906a2b433f9c4396fd51d9814e72506a02f75e623a462
7
- data.tar.gz: 25240f1221131cfea87c90e6bada749cdb5fd52cf25d2ba936977fa7d142f2ae25e23b1e9955086a02e9178987fc7a40d26e7855c096c05e71b2c504f0e4e9e9
6
+ metadata.gz: cea6a62ae70be12318f9d46209add1cace49be33745d7cefedd8eec3de5a8b319a759839c24a950c8bc6c814c21ce6eb8afebcbbac1c41e464c7e78989433d80
7
+ data.tar.gz: d90297aa8f6a80d1314d692b087a3fe5a1f8d1fea071762610eceb03661d346d1654bc62be2cf1f2c9181ba38c49103ef0c862c0210daec0d5b7e92516597175
@@ -1,4 +1,3 @@
1
- //= link decidim/proposals/social_share.js
2
1
  //= link decidim/proposals/add_proposal.js
3
2
  //= link decidim/proposals/admin/proposals_form.js
4
3
  //= link_tree ../images/decidim
@@ -20,4 +20,9 @@ $(() => {
20
20
  toggleDisabledHiddenFields();
21
21
 
22
22
  }
23
+
24
+ $(document).on("closed.zf.callout", (event) => {
25
+ $(event.target).remove();
26
+ });
27
+
23
28
  });
@@ -32,6 +32,7 @@ module Decidim
32
32
 
33
33
  def badge_classes
34
34
  return super unless options[:full_badge]
35
+
35
36
  state_classes.concat(["label", "collaborative-draft-status"]).join(" ")
36
37
  end
37
38
 
@@ -14,6 +14,7 @@ module Decidim
14
14
 
15
15
  def show
16
16
  return unless endorsers.any?
17
+
17
18
  render
18
19
  end
19
20
 
@@ -10,6 +10,7 @@ module Decidim
10
10
  class IrreversibleActionModalCell < Decidim::ViewModel
11
11
  def show
12
12
  return unless action.presence
13
+
13
14
  render :show
14
15
  end
15
16
 
@@ -1,18 +1,18 @@
1
1
  <div class="columns mediumlarge-4 hidden-section p-sm">
2
2
  <div class="medium-8">
3
3
  <%= follow_button_for(model, true) %>
4
- <% if amendments_enabled? %>
5
- <div class="button-group button-group--collapse mb-s row collapse">
4
+ <% if amendmendment_creation_enabled? || visible_emendations.any? %>
5
+ <div class="button-group button-group--collapse mb-s row collapse amend-buttons">
6
6
  <%= link_to resource_amendments_path, class: "column medium-4 button light secondary" do %>
7
- <%= model.emendations.count %>
8
- <% end %>
9
- <%= link_to amend_resource_path, class: "column button hollow secondary button--sc" do %>
10
- <%= t("amend", scope: "decidim.proposals.participatory_text_proposal.buttons") %>
11
- <% end %>
7
+ <%= visible_emendations.count %>
8
+ <% end %>
9
+ <%= link_to amend_resource_path, class: "column button hollow secondary button--sc", disabled: amend_button_disabled? do %>
10
+ <%= t("amend", scope: "decidim.proposals.participatory_text_proposal.buttons") %>
11
+ <% end %>
12
12
  </div>
13
13
  <% end %>
14
14
  <% if component_settings.comments_enabled? %>
15
- <div class="button-group button-group--collapse row collapse">
15
+ <div class="button-group button-group--collapse row collapse comment-buttons">
16
16
  <% if current_settings.comments_blocked? %>
17
17
  <%= content_tag :button, class: "column medium-4 button light secondary", title: t("endorse", scope: "decidim.proposals.participatory_text_proposal.buttons") do %>
18
18
  <%= icon "comment-square", class: "icon--small", aria_label: t("comments", scope: "decidim.proposals.participatory_text_proposal.buttons"), role: "img" %>
@@ -33,6 +33,7 @@ module Decidim
33
33
 
34
34
  def body
35
35
  return unless model.participatory_text_level == "article"
36
+
36
37
  formatted = simple_format(present(model).body)
37
38
  decidim_sanitize(strip_links(formatted))
38
39
  end
@@ -72,6 +73,18 @@ module Decidim
72
73
  def participatory_space_type_name
73
74
  translated_attribute current_participatory_space.model_name.human
74
75
  end
76
+
77
+ def visible_emendations
78
+ @visible_emendations ||= model.visible_emendations_for(current_user)
79
+ end
80
+
81
+ def amendmendment_creation_enabled?
82
+ (current_component.settings.amendments_enabled? && current_settings.amendment_creation_enabled?)
83
+ end
84
+
85
+ def amend_button_disabled?
86
+ !amendmendment_creation_enabled?
87
+ end
75
88
  end
76
89
  end
77
90
  end
@@ -5,19 +5,15 @@ require "cell/partial"
5
5
  module Decidim
6
6
  module Proposals
7
7
  # This cell renders the link to the source collaborative draft of a proposal.
8
- class ProposalLinkToCollaborativeDraftCell < Decidim::ViewModel
9
- def show
10
- render if collaborative_draft
11
- end
12
-
8
+ class ProposalLinkToCollaborativeDraftCell < ProposalLinkedResourcesCell
13
9
  private
14
10
 
15
- def collaborative_draft
16
- @collaborative_draft ||= model.linked_resources(:collaborative_draft, "created_from_collaborative_draft").first
11
+ def linked_resource
12
+ @linked_resource ||= model.linked_resources(:collaborative_draft, "created_from_collaborative_draft").first
17
13
  end
18
14
 
19
15
  def link_to_resource
20
- link_to resource_locator(collaborative_draft).path, class: "link" do
16
+ link_to resource_locator(linked_resource).path, class: "link" do
21
17
  t("link_to_collaborative_draft_text", scope: "decidim.proposals.proposals.show")
22
18
  end
23
19
  end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cell/partial"
4
+
5
+ module Decidim
6
+ module Proposals
7
+ # This cell renders the link to the rejected emendation promoted to proposal.
8
+ class ProposalLinkToRejectedEmendationCell < ProposalLinkedResourcesCell
9
+ private
10
+
11
+ def linked_resource
12
+ @linked_resource ||= model.linked_promoted_resource
13
+ end
14
+
15
+ def link_to_resource
16
+ link_to resource_locator(linked_resource).path, class: "link" do
17
+ if model.emendation?
18
+ t("link_to_proposal_from_emendation_text", scope: "decidim.proposals.proposals.show")
19
+ else
20
+ t("link_to_promoted_emendation_text", scope: "decidim.proposals.proposals.show")
21
+ end
22
+ end
23
+ end
24
+
25
+ def link_help_text
26
+ if model.emendation?
27
+ t("link_to_proposal_from_emendation_help_text", scope: "decidim.proposals.proposals.show")
28
+ else
29
+ t("link_to_promoted_emendation_help_text", scope: "decidim.proposals.proposals.show")
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,9 @@
1
+ <div class="text-center mt-sm">
2
+ <%= link_to_resource %>
3
+
4
+ <div class="text-center">
5
+ <small>
6
+ <%= link_help_text %>
7
+ </small>
8
+ </div>
9
+ </div>
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cell/partial"
4
+
5
+ module Decidim
6
+ module Proposals
7
+ # This cell renders the linked resource of a proposal.
8
+ class ProposalLinkedResourcesCell < Decidim::ViewModel
9
+ def show
10
+ render if linked_resource
11
+ end
12
+ end
13
+ end
14
+ end
@@ -36,6 +36,7 @@ module Decidim
36
36
 
37
37
  def has_footer?
38
38
  return false if model.emendation?
39
+
39
40
  true
40
41
  end
41
42
 
@@ -45,12 +46,14 @@ module Decidim
45
46
 
46
47
  def badge_classes
47
48
  return super unless options[:full_badge]
49
+
48
50
  state_classes.concat(["label", "proposal-status"]).join(" ")
49
51
  end
50
52
 
51
53
  def statuses
52
54
  return [:endorsements_count, :comments_count] if model.draft?
53
55
  return [:creation_date, :endorsements_count, :comments_count] if !has_link_to_resource? || !can_be_followed?
56
+
54
57
  [:creation_date, :follow, :endorsements_count, :comments_count]
55
58
  end
56
59
 
@@ -5,6 +5,8 @@ module Decidim
5
5
  module Admin
6
6
  # A command with all the business logic when a user creates a new proposal.
7
7
  class CreateProposal < Rectify::Command
8
+ include AttachmentMethods
9
+ include GalleryMethods
8
10
  include HashtagsMethods
9
11
 
10
12
  # Public: Initializes the command.
@@ -28,9 +30,15 @@ module Decidim
28
30
  return broadcast(:invalid) if attachment_invalid?
29
31
  end
30
32
 
33
+ if process_gallery?
34
+ build_gallery
35
+ return broadcast(:invalid) if gallery_invalid?
36
+ end
37
+
31
38
  transaction do
32
39
  create_proposal
33
40
  create_attachment if process_attachments?
41
+ create_gallery if process_gallery?
34
42
  send_notification
35
43
  end
36
44
 
@@ -39,7 +47,7 @@ module Decidim
39
47
 
40
48
  private
41
49
 
42
- attr_reader :form, :proposal, :attachment
50
+ attr_reader :form, :proposal, :attachment, :gallery
43
51
 
44
52
  def create_proposal
45
53
  @proposal = Decidim::Proposals::ProposalBuilder.create(
@@ -47,6 +55,7 @@ module Decidim
47
55
  author: form.author,
48
56
  action_user: form.current_user
49
57
  )
58
+ @attached_to = @proposal
50
59
  end
51
60
 
52
61
  def attributes
@@ -64,38 +73,6 @@ module Decidim
64
73
  }
65
74
  end
66
75
 
67
- def build_attachment
68
- @attachment = Attachment.new(
69
- title: form.attachment.title,
70
- file: form.attachment.file,
71
- attached_to: @proposal
72
- )
73
- end
74
-
75
- def attachment_invalid?
76
- if attachment.invalid? && attachment.errors.has_key?(:file)
77
- form.attachment.errors.add :file, attachment.errors[:file]
78
- true
79
- end
80
- end
81
-
82
- def attachment_present?
83
- form.attachment.file.present?
84
- end
85
-
86
- def create_attachment
87
- attachment.attached_to = proposal
88
- attachment.save!
89
- end
90
-
91
- def attachments_allowed?
92
- form.current_component.settings.attachments_allowed?
93
- end
94
-
95
- def process_attachments?
96
- attachments_allowed? && attachment_present?
97
- end
98
-
99
76
  def send_notification
100
77
  Decidim::EventsManager.publish(
101
78
  event: "decidim.events.proposals.proposal_published",
@@ -28,6 +28,8 @@ module Decidim
28
28
  end
29
29
 
30
30
  broadcast(:ok)
31
+ rescue StandardError
32
+ broadcast(:invalid_file)
31
33
  end
32
34
 
33
35
  private
@@ -40,6 +40,7 @@ module Decidim
40
40
 
41
41
  def proposals_to_link
42
42
  return previous_links if form.same_component?
43
+
43
44
  form.proposals
44
45
  end
45
46
 
@@ -39,7 +39,7 @@ module Decidim
39
39
 
40
40
  def publish_drafts
41
41
  Decidim::Proposals::Proposal.where(component: form.current_component).drafts.find_each do |proposal|
42
- add_failure(proposal) unless proposal.update(published_at: Time.current)
42
+ add_failure(proposal) unless publish_proposal(proposal)
43
43
  end
44
44
  raise ActiveRecord::Rollback if @failures.any?
45
45
  end
@@ -47,6 +47,29 @@ module Decidim
47
47
  def add_failure(proposal)
48
48
  @failures[proposal.id] = proposal.errors.full_messages
49
49
  end
50
+
51
+ # This will be the PaperTrail version shown in the version control feature (1 of 1).
52
+ # For an attribute to appear in the new version it has to be reset
53
+ # and reassigned, as PaperTrail only keeps track of object CHANGES.
54
+ def publish_proposal(proposal)
55
+ title, body = reset_proposal_title_and_body(proposal)
56
+
57
+ Decidim.traceability.perform_action!(:create, proposal, form.current_user, visibility: "all") do
58
+ proposal.update(title: title, body: body, published_at: Time.current)
59
+ end
60
+ end
61
+
62
+ # Reset the attributes to an empty string and return the old values.
63
+ def reset_proposal_title_and_body(proposal)
64
+ title = proposal.title
65
+ body = proposal.body
66
+
67
+ PaperTrail.request(enabled: false) do
68
+ proposal.update_columns(title: "", body: "") # rubocop:disable Rails/SkipsModelValidations
69
+ end
70
+
71
+ [title, body]
72
+ end
50
73
  end
51
74
  end
52
75
  end
@@ -35,14 +35,18 @@ module Decidim
35
35
 
36
36
  attr_reader :form
37
37
 
38
+ # Prevents PaperTrail from creating versions while updating participatory text proposals.
39
+ # A first version will be created when publishing the Participatory Text.
38
40
  def update_contents_and_resort_proposals(form)
39
- form.proposals.each do |prop_form|
40
- proposal = Decidim::Proposals::Proposal.where(component: form.current_component).find(prop_form.id)
41
- proposal.set_list_position(prop_form.position) if proposal.position != prop_form.position
42
- proposal.title = prop_form.title
43
- proposal.body = prop_form.body if proposal.participatory_text_level == Decidim::Proposals::ParticipatoryTextSection::LEVELS[:article]
44
-
45
- add_failure(proposal) unless proposal.save
41
+ PaperTrail.request(enabled: false) do
42
+ form.proposals.each do |prop_form|
43
+ proposal = Proposal.where(component: form.current_component).find(prop_form.id)
44
+ proposal.set_list_position(prop_form.position) if proposal.position != prop_form.position
45
+ proposal.title = prop_form.title
46
+ proposal.body = prop_form.body if proposal.participatory_text_level == ParticipatoryTextSection::LEVELS[:article]
47
+
48
+ add_failure(proposal) unless proposal.save
49
+ end
46
50
  end
47
51
  raise ActiveRecord::Rollback if @failures.any?
48
52
  end
@@ -6,6 +6,7 @@ module Decidim
6
6
  # A command with all the business logic when a user updates a proposal.
7
7
  class UpdateProposal < Rectify::Command
8
8
  include AttachmentMethods
9
+ include GalleryMethods
9
10
  include HashtagsMethods
10
11
 
11
12
  # Public: Initializes the command.
@@ -34,10 +35,17 @@ module Decidim
34
35
  return broadcast(:invalid) if attachment_invalid?
35
36
  end
36
37
 
38
+ if process_gallery?
39
+ build_gallery
40
+ return broadcast(:invalid) if gallery_invalid?
41
+ end
42
+
37
43
  transaction do
38
44
  update_proposal
39
45
  update_proposal_author
40
46
  create_attachment if process_attachments?
47
+ create_gallery if process_gallery?
48
+ photo_cleanup!
41
49
  end
42
50
 
43
51
  broadcast(:ok, proposal)
@@ -45,7 +53,7 @@ module Decidim
45
53
 
46
54
  private
47
55
 
48
- attr_reader :form, :proposal, :attachment
56
+ attr_reader :form, :proposal, :attachment, :gallery
49
57
 
50
58
  def update_proposal
51
59
  Decidim.traceability.update!(
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Proposals
5
+ # A module with all the gallery common methods for proposals
6
+ # and collaborative draft commands.
7
+ # Allows to create several image attachments at once
8
+ module GalleryMethods
9
+ private
10
+
11
+ def build_gallery
12
+ @gallery = []
13
+ @form.add_photos.each do |photo|
14
+ next unless image? photo
15
+
16
+ @gallery << Attachment.new(
17
+ title: photo.original_filename,
18
+ file: photo,
19
+ attached_to: @attached_to
20
+ )
21
+ end
22
+ end
23
+
24
+ def image?(image)
25
+ return unless image.respond_to? :content_type
26
+
27
+ image.content_type.start_with? "image"
28
+ end
29
+
30
+ def gallery_invalid?
31
+ gallery.each do |photo|
32
+ if photo.invalid? && photo.errors.has_key?(:file)
33
+ @form.errors.add(:add_photos, photo.errors[:file])
34
+ return true
35
+ end
36
+ end
37
+ false
38
+ end
39
+
40
+ def create_gallery
41
+ @gallery.map! do |photo|
42
+ photo.attached_to = @attached_to
43
+ photo.save!
44
+ @form.photos << photo.id.to_s
45
+ end
46
+ end
47
+
48
+ def photo_cleanup!
49
+ @attached_to.photos.each do |photo|
50
+ photo.destroy! if @form.photos.exclude? photo.id.to_s
51
+ end
52
+ # manually reset cached photos
53
+ @attached_to.reload
54
+ @attached_to.instance_variable_set(:@photos, nil)
55
+ end
56
+
57
+ # maybe a custom settings options would be nice
58
+ def gallery_allowed?
59
+ @form.current_component.settings.attachments_allowed?
60
+ end
61
+
62
+ def process_gallery?
63
+ gallery_allowed? && @form.add_photos.any?
64
+ end
65
+ end
66
+ end
67
+ end