decidim-meetings 0.19.0 → 0.22.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/decidim_meetings_manifest.js +1 -0
  3. data/app/assets/images/decidim/gamification/badges/attended_meetings.svg +1 -106
  4. data/app/assets/images/decidim/meetings/icon.svg +1 -5
  5. data/app/assets/javascripts/decidim/meetings/admin/destroy_meeting_alert.js.es6 +16 -0
  6. data/app/cells/decidim/meetings/highlighted_meetings_for_component/show.erb +7 -7
  7. data/app/cells/decidim/meetings/join_meeting_button/show.erb +2 -2
  8. data/app/cells/decidim/meetings/meeting_cell.rb +2 -1
  9. data/app/cells/decidim/meetings/meeting_list_item/show.erb +3 -3
  10. data/app/cells/decidim/meetings/meeting_list_item_cell.rb +1 -1
  11. data/app/cells/decidim/meetings/meeting_m/date.erb +1 -1
  12. data/app/cells/decidim/meetings/meeting_m/footer.erb +1 -1
  13. data/app/cells/decidim/meetings/meeting_m/multiple_dates.erb +1 -1
  14. data/app/cells/decidim/meetings/meeting_m_cell.rb +2 -2
  15. data/app/cells/decidim/meetings/meeting_s/show.erb +6 -6
  16. data/app/commands/decidim/meetings/admin/destroy_meeting.rb +6 -1
  17. data/app/commands/decidim/meetings/join_meeting.rb +11 -0
  18. data/app/controllers/decidim/meetings/admin/meeting_closes_controller.rb +2 -0
  19. data/app/controllers/decidim/meetings/admin/meetings_controller.rb +10 -0
  20. data/app/controllers/decidim/meetings/calendars_controller.rb +1 -0
  21. data/app/controllers/decidim/meetings/directory/meetings_controller.rb +1 -1
  22. data/app/controllers/decidim/meetings/registrations_controller.rb +1 -1
  23. data/app/forms/decidim/meetings/admin/close_meeting_form.rb +7 -1
  24. data/app/helpers/decidim/meetings/application_helper.rb +1 -0
  25. data/app/helpers/decidim/meetings/map_helper.rb +2 -1
  26. data/app/helpers/decidim/meetings/meetings_helper.rb +1 -1
  27. data/app/models/decidim/meetings/meeting.rb +18 -0
  28. data/app/presenters/decidim/meetings/meeting_presenter.rb +14 -3
  29. data/app/queries/decidim/meetings/filtered_meetings.rb +37 -0
  30. data/app/queries/decidim/meetings/metrics/meetings_metric_manage.rb +2 -8
  31. data/app/services/decidim/meetings/calendar/meeting_to_event.rb +3 -3
  32. data/app/types/decidim/meetings/agenda_item_type.rb +28 -0
  33. data/app/types/decidim/meetings/agenda_type.rb +25 -0
  34. data/app/types/decidim/meetings/meeting_type.rb +35 -8
  35. data/app/types/decidim/meetings/meetings_type.rb +1 -1
  36. data/app/types/decidim/meetings/minutes_type.rb +26 -0
  37. data/app/types/decidim/meetings/service_type.rb +13 -0
  38. data/app/views/decidim/meetings/_calendar_modal.html.erb +4 -4
  39. data/app/views/decidim/meetings/admin/invites/index.html.erb +2 -2
  40. data/app/views/decidim/meetings/admin/meeting_closes/_form.html.erb +1 -6
  41. data/app/views/decidim/meetings/admin/meeting_closes/proposals_picker.html.erb +1 -0
  42. data/app/views/decidim/meetings/admin/meetings/_form.html.erb +4 -1
  43. data/app/views/decidim/meetings/admin/meetings/index.html.erb +18 -1
  44. data/app/views/decidim/meetings/admin/registrations/_form.html.erb +4 -0
  45. data/app/views/decidim/meetings/directory/meetings/index.html.erb +5 -3
  46. data/app/views/decidim/meetings/meetings/_filters.html.erb +12 -4
  47. data/app/views/decidim/meetings/meetings/_linked_meetings.html.erb +2 -2
  48. data/app/views/decidim/meetings/meetings/_meeting_agenda.html.erb +2 -2
  49. data/app/views/decidim/meetings/meetings/_meeting_minutes.html.erb +8 -8
  50. data/app/views/decidim/meetings/meetings/index.html.erb +1 -1
  51. data/app/views/decidim/meetings/meetings/show.html.erb +13 -4
  52. data/app/views/decidim/participatory_processes/participatory_process_groups/_meeting.html.erb +2 -2
  53. data/app/views/decidim/participatory_spaces/_conference_venues.html.erb +1 -1
  54. data/app/views/decidim/participatory_spaces/_upcoming_meeting_for_card.html.erb +1 -3
  55. data/config/locales/ar.yml +4 -0
  56. data/config/locales/bg-BG.yml +29 -0
  57. data/config/locales/ca.yml +15 -1
  58. data/config/locales/cs.yml +18 -0
  59. data/config/locales/da-DK.yml +1 -0
  60. data/config/locales/de.yml +15 -0
  61. data/config/locales/el-GR.yml +1 -0
  62. data/config/locales/el.yml +454 -0
  63. data/config/locales/en.yml +16 -2
  64. data/config/locales/es-MX.yml +16 -2
  65. data/config/locales/es-PY.yml +16 -2
  66. data/config/locales/es.yml +16 -2
  67. data/config/locales/et-EE.yml +1 -0
  68. data/config/locales/eu.yml +2 -2
  69. data/config/locales/fi-plain.yml +14 -0
  70. data/config/locales/fi.yml +41 -27
  71. data/config/locales/fr-CA.yml +454 -0
  72. data/config/locales/fr.yml +6 -0
  73. data/config/locales/ga-IE.yml +1 -0
  74. data/config/locales/hr-HR.yml +1 -0
  75. data/config/locales/hu.yml +14 -2
  76. data/config/locales/is-IS.yml +234 -0
  77. data/config/locales/it.yml +16 -2
  78. data/config/locales/ja-JP.yml +455 -0
  79. data/config/locales/lt-LT.yml +1 -0
  80. data/config/locales/lv-LV.yml +452 -0
  81. data/config/locales/mt-MT.yml +1 -0
  82. data/config/locales/nl.yml +48 -42
  83. data/config/locales/no.yml +446 -0
  84. data/config/locales/pl.yml +20 -1
  85. data/config/locales/pt-BR.yml +1 -1
  86. data/config/locales/pt.yml +186 -171
  87. data/config/locales/ro-RO.yml +459 -0
  88. data/config/locales/ru.yml +52 -0
  89. data/config/locales/sk-SK.yml +463 -0
  90. data/config/locales/sk.yml +463 -0
  91. data/config/locales/sl.yml +10 -0
  92. data/config/locales/sr-CS.yml +13 -0
  93. data/config/locales/sv.yml +11 -5
  94. data/config/locales/uk.yml +0 -2
  95. data/db/migrate/20200320105922_index_foreign_keys_in_decidim_meetings_registrations.rb +7 -0
  96. data/lib/decidim/api/linked_resources_interface.rb +17 -0
  97. data/lib/decidim/api/services_interface.rb +19 -0
  98. data/lib/decidim/meetings.rb +1 -0
  99. data/lib/decidim/meetings/admin_engine.rb +3 -1
  100. data/lib/decidim/meetings/api.rb +8 -0
  101. data/lib/decidim/meetings/component.rb +6 -3
  102. data/lib/decidim/meetings/engine.rb +0 -4
  103. data/lib/decidim/meetings/seeds/city.jpeg +0 -0
  104. data/lib/decidim/meetings/version.rb +1 -1
  105. data/lib/tasks/decidim_meetings.rake +16 -0
  106. metadata +53 -18
  107. data/app/views/decidim/meetings/meeting_widgets/show.html.erb +0 -9
@@ -4,6 +4,7 @@ module Decidim
4
4
  module Meetings
5
5
  # This helper include some methods for rendering meetings dynamic maps.
6
6
  module MapHelper
7
+ include Decidim::SanitizeHelper
7
8
  # Serialize a collection of geocoded meetings to be used by the dynamic map component
8
9
  #
9
10
  # meetings - A collection of meetings
@@ -18,7 +19,7 @@ module Decidim
18
19
  startTime: "#{meeting.start_time.strftime("%H:%M")} - #{meeting.end_time.strftime("%H:%M")}",
19
20
  icon: icon("meetings", width: 40, height: 70, remove_icon_class: true),
20
21
  location: translated_attribute(meeting.location),
21
- locationHints: translated_attribute(meeting.location_hints),
22
+ locationHints: decidim_html_escape(translated_attribute(meeting.location_hints)),
22
23
  link: resource_locator(meeting).path)
23
24
  end
24
25
  end
@@ -16,7 +16,7 @@ module Decidim
16
16
  # Returns the meeting's description truncated.
17
17
  def meeting_description(meeting, max_length = 120)
18
18
  link = resource_locator(meeting).path
19
- description = present(meeting).description
19
+ description = CGI.unescapeHTML present(meeting).description
20
20
  tail = "... #{link_to(t("read_more", scope: "decidim.meetings"), link)}".html_safe
21
21
  CGI.unescapeHTML html_truncate(description, max_length: max_length, tail: tail)
22
22
  end
@@ -20,6 +20,7 @@ module Decidim
20
20
  include Decidim::Hashtaggable
21
21
  include Decidim::Forms::HasQuestionnaire
22
22
  include Decidim::Paddable
23
+ include Decidim::ActsAsAuthor
23
24
 
24
25
  belongs_to :organizer, foreign_key: "organizer_id", class_name: "Decidim::User", optional: true
25
26
  has_many :registrations, class_name: "Decidim::Meetings::Registration", foreign_key: "decidim_meeting_id", dependent: :destroy
@@ -61,6 +62,12 @@ module Decidim
61
62
  registrations.where.not(decidim_user_group_id: nil)
62
63
  end
63
64
 
65
+ # Returns the presenter for this author, to be used in the views.
66
+ # Required by ActsAsAuthor.
67
+ def presenter
68
+ Decidim::Meetings::MeetingPresenter.new(self)
69
+ end
70
+
64
71
  def self.log_presenter_class_for(_log)
65
72
  Decidim::Meetings::AdminLog::MeetingPresenter
66
73
  end
@@ -166,6 +173,17 @@ module Decidim
166
173
  (Time.current - end_time) < 72.hours
167
174
  end
168
175
 
176
+ def authored_proposals
177
+ Decidim::Proposals::Proposal
178
+ .joins(:coauthorships)
179
+ .where(
180
+ decidim_coauthorships: {
181
+ decidim_author_type: "Decidim::Meetings::Meeting",
182
+ decidim_author_id: id
183
+ }
184
+ )
185
+ end
186
+
169
187
  private
170
188
 
171
189
  def can_participate_in_meeting?(user)
@@ -18,8 +18,7 @@ module Decidim
18
18
  return unless meeting
19
19
 
20
20
  handle_locales(meeting.title, all_locales) do |content|
21
- content = decidim_html_escape(content)
22
- renderer = Decidim::ContentRenderers::HashtagRenderer.new(content)
21
+ renderer = Decidim::ContentRenderers::HashtagRenderer.new(decidim_html_escape(content))
23
22
  renderer.render(links: links).html_safe
24
23
  end
25
24
  end
@@ -28,7 +27,7 @@ module Decidim
28
27
  return unless meeting
29
28
 
30
29
  handle_locales(meeting.description, all_locales) do |content|
31
- renderer = Decidim::ContentRenderers::HashtagRenderer.new(content)
30
+ renderer = Decidim::ContentRenderers::HashtagRenderer.new(decidim_sanitize(content))
32
31
  renderer.render(links: links).html_safe
33
32
  end
34
33
  end
@@ -66,6 +65,18 @@ module Decidim
66
65
  false
67
66
  end
68
67
 
68
+ def proposals
69
+ return unless meeting
70
+
71
+ @proposals ||= meeting.authored_proposals.load
72
+ end
73
+
74
+ def formatted_proposals_titles
75
+ return unless meeting
76
+
77
+ proposals.map.with_index { |proposal, index| "#{index + 1}) #{proposal.title}\n" }
78
+ end
79
+
69
80
  private
70
81
 
71
82
  def handle_locales(content, all_locales)
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Meetings
5
+ # A class used to find meetings filtered by components and a date range
6
+ class FilteredMeetings < Rectify::Query
7
+ # Syntactic sugar to initialize the class and return the queried objects.
8
+ #
9
+ # components - An array of Decidim::Component
10
+ # start_at - A date to filter resources created after it
11
+ # end_at - A date to filter resources created before it.
12
+ def self.for(components, start_at = nil, end_at = nil)
13
+ new(components, start_at, end_at).query
14
+ end
15
+
16
+ # Initializes the class.
17
+ #
18
+ # components - An array of Decidim::Component
19
+ # start_at - A date to filter resources created after it
20
+ # end_at - A date to filter resources created before it.
21
+ def initialize(components, start_at = nil, end_at = nil)
22
+ @components = components
23
+ @start_at = start_at
24
+ @end_at = end_at
25
+ end
26
+
27
+ # Finds the Projects scoped to an array of components and filtered
28
+ # by a range of dates.
29
+ def query
30
+ meetings = Decidim::Meetings::Meeting.where(component: @components)
31
+ meetings = meetings.where("created_at >= ?", @start_at) if @start_at.present?
32
+ meetings = meetings.where("created_at <= ?", @end_at) if @end_at.present?
33
+ meetings
34
+ end
35
+ end
36
+ end
37
+ end
@@ -9,9 +9,6 @@ module Decidim
9
9
  end
10
10
 
11
11
  def save
12
- return @registry if @registry
13
-
14
- @registry = []
15
12
  cumulative.each do |key, cumulative_value|
16
13
  next if cumulative_value.zero?
17
14
 
@@ -21,10 +18,8 @@ module Decidim
21
18
  organization: @organization, decidim_category_id: category_id,
22
19
  participatory_space_type: space_type, participatory_space_id: space_id)
23
20
  record.assign_attributes(cumulative: cumulative_value, quantity: quantity_value)
24
- @registry << record
21
+ record.save!
25
22
  end
26
- @registry.each(&:save!)
27
- @registry
28
23
  end
29
24
 
30
25
  private
@@ -35,8 +30,7 @@ module Decidim
35
30
  spaces = Decidim.participatory_space_manifests.flat_map do |manifest|
36
31
  manifest.participatory_spaces.call(@organization).public_spaces
37
32
  end
38
- components = Decidim::Component.where(participatory_space: spaces).published
39
- @query = Decidim::Meetings::Meeting.where(component: components).joins(:component)
33
+ @query = Decidim::Meetings::Meeting.where(component: visible_component_ids_from_spaces(spaces)).joins(:component)
40
34
  .left_outer_joins(:category).visible
41
35
  @query = @query.where("decidim_meetings_meetings.created_at <= ?", end_time)
42
36
  @query = @query.group("decidim_categorizations.decidim_category_id",
@@ -36,10 +36,10 @@ module Decidim
36
36
  return @event if @event
37
37
 
38
38
  @event = Icalendar::Event.new
39
- @event.dtstart = Icalendar::Values::DateTime.new(meeting.start_time)
40
- @event.dtend = Icalendar::Values::DateTime.new(meeting.end_time)
39
+ @event.dtstart = Icalendar::Values::DateTime.new(meeting.start_time.utc, "tzid" => "UTC")
40
+ @event.dtend = Icalendar::Values::DateTime.new(meeting.end_time.utc, "tzid" => "UTC")
41
41
  @event.summary = present(meeting).title
42
- @event.description = strip_tags(present(meeting).description)
42
+ @event.description = strip_tags(CGI.unescapeHTML(present(meeting).description))
43
43
  @event.location = meeting.address
44
44
  @event.geo = [meeting.latitude, meeting.longitude]
45
45
  @event.url = url_for(meeting)
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Meetings
5
+ AgendaItemType = GraphQL::ObjectType.define do
6
+ name "MeetingAgendaItem"
7
+ description "A meeting agenda item"
8
+
9
+ field :id, !types.ID, "The ID for this agenda item"
10
+ field :title, Decidim::Core::TranslatedFieldType, "The title for this agenda item"
11
+ field :description, Decidim::Core::TranslatedFieldType, "The description for this agenda item"
12
+ field :items, !types[AgendaItemType], "Sub-items (children) of this agenda item", property: :agenda_item_children
13
+ field :parent, AgendaItemType, "Parent agenda item, if available"
14
+ field :agenda, AgendaType, "Belonging agenda"
15
+ field :duration, !types.Int, "Duration in number of minutes for this item in this agenda"
16
+ field :position, !types.Int, "Order position for this agenda item"
17
+
18
+ field :createdAt, Decidim::Core::DateTimeType do
19
+ description "The date and time this agenda item was created"
20
+ property :created_at
21
+ end
22
+ field :updatedAt, Decidim::Core::DateTimeType do
23
+ description "The date and time this agenda item was updated"
24
+ property :updated_at
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Meetings
5
+ AgendaType = GraphQL::ObjectType.define do
6
+ name "MeetingAgenda"
7
+ description "A meeting agenda"
8
+
9
+ field :id, !types.ID, "The ID for the agenda"
10
+ field :title, Decidim::Core::TranslatedFieldType, "The title for the agenda"
11
+ field :items, !types[AgendaItemType], "Items and sub-items of the agenda", property: :agenda_items
12
+ # probably useful in the future, when handling user permissions
13
+ # field :visible, !types.Boolean, "Whether this minutes is public or not", property: :visible
14
+
15
+ field :createdAt, Decidim::Core::DateTimeType do
16
+ description "The date and time this agenda was created"
17
+ property :created_at
18
+ end
19
+ field :updatedAt, Decidim::Core::DateTimeType do
20
+ description "The date and time this agenda was updated"
21
+ property :updated_at
22
+ end
23
+ end
24
+ end
25
+ end
@@ -10,24 +10,51 @@ module Decidim
10
10
  -> { Decidim::Comments::CommentableInterface },
11
11
  -> { Decidim::Core::CategorizableInterface },
12
12
  -> { Decidim::Core::ScopableInterface },
13
- -> { Decidim::Core::AttachableInterface }
13
+ -> { Decidim::Core::AttachableInterface },
14
+ -> { Decidim::Core::TimestampsInterface },
15
+ -> { Decidim::Meetings::ServicesInterface },
16
+ -> { Decidim::Meetings::LinkedResourcesInterface },
17
+ -> { Decidim::Forms::QuestionnaireEntityInterface }
14
18
  ]
15
19
 
16
- field :id, !types.ID
17
- field :reference, !types.String
20
+ field :id, !types.ID, "ID of this meeting"
21
+ field :reference, !types.String, "Reference for this meeting"
18
22
  field :title, !Decidim::Core::TranslatedFieldType, "The title of this meeting."
23
+ field :description, Decidim::Core::TranslatedFieldType, "The description of this meeting."
19
24
  field :startTime, !Decidim::Core::DateTimeType, "The time this meeting starts", property: :start_time
20
25
  field :endTime, !Decidim::Core::DateTimeType, "The time this meeting ends", property: :end_time
26
+ field :organizer, Decidim::Core::AuthorInterface, "If specified, the organizer of this meeting"
27
+ field :agenda, AgendaType, "Agenda for this meeting, if available" do
28
+ resolve ->(meeting, _args, _ctx) {
29
+ meeting.agenda if meeting.agenda&.visible?
30
+ }
31
+ end
21
32
 
22
33
  field :closed, !types.Boolean, "Whether this meeting is closed or not.", property: :closed?
23
34
  field :closingReport, Decidim::Core::TranslatedFieldType, "The closing report of this meeting.", property: :closing_report
24
-
25
- field :registrationsEnabled, !types.Boolean, "Whether the registrations are enabled or not", property: :registrations_enabled
26
- field :remainingSlots, types.Int, "Amount of slots available for this meeting", property: :remaining_slots
35
+ field :attendingOrganizations, types.String, "list of attending organizations", property: :attending_organizations
27
36
  field :attendeeCount, types.Int, "Amount of attendees to this meeting", property: :attendees_count
28
37
  field :contributionCount, types.Int, "Amount of contributions to this meeting", property: :contributions_count
29
-
30
- field :address, types.String, "The physical address of this meeting"
38
+ field :minutes, MinutesType, "Minutes for this meeting, if available" do
39
+ resolve ->(meeting, _args, _ctx) {
40
+ meeting.minutes if meeting.minutes&.visible?
41
+ }
42
+ end
43
+ field :privateMeeting, !types.Boolean, "Whether the meeting is private or not (it can only be true if transparent)", property: :private_meeting
44
+ field :transparent, !types.Boolean, "For private meetings, information is public if transparent", property: :transparent
45
+ field :registrationsEnabled, !types.Boolean, "Whether the registrations are enabled or not", property: :registrations_enabled
46
+ field :registrationTerms, Decidim::Core::TranslatedFieldType, "The registration terms", property: :registration_terms
47
+ field :remainingSlots, types.Int, "Amount of slots available for this meeting", property: :remaining_slots
48
+ field :registrationFormEnabled, !types.Boolean, "Whether the registrations have a form or not", property: :registration_form_enabled
49
+ field :registrationForm, Decidim::Forms::QuestionnaireType do
50
+ description "If registration requires to fill a form, this is the questionnaire"
51
+ resolve ->(meeting, _args, _ctx) {
52
+ meeting.questionnaire if meeting.registration_form_enabled?
53
+ }
54
+ end
55
+ field :location, Decidim::Core::TranslatedFieldType, "The location of this meeting (free format)"
56
+ field :locationHints, Decidim::Core::TranslatedFieldType, "The location of this meeting (free format)", property: :location_hints
57
+ field :address, types.String, "The physical address of this meeting (used for geolocation)"
31
58
  field :coordinates, Decidim::Core::CoordinatesType, "Physical coordinates for this meeting" do
32
59
  resolve ->(meeting, _args, _ctx) {
33
60
  [meeting.latitude, meeting.longitude]
@@ -25,7 +25,7 @@ module Decidim
25
25
 
26
26
  module MeetingsTypeHelper
27
27
  def self.base_scope(component)
28
- Meeting.where(component: component)
28
+ Meeting.visible.where(component: component)
29
29
  end
30
30
  end
31
31
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Meetings
5
+ MinutesType = GraphQL::ObjectType.define do
6
+ name "MeetingMinutes"
7
+ description "A meeting minutes"
8
+
9
+ field :id, !types.ID, "The ID for the minutes"
10
+ field :description, Decidim::Core::TranslatedFieldType, "The description for the minutes"
11
+ field :videoUrl, types.String, "URL for the video of the session, if any", property: :video_url
12
+ field :audioUrl, types.String, "URL for the audio of the session, if any", property: :audio_url
13
+ # probably useful in the future, when handling user permissions
14
+ # field :visible, !types.Boolean, "Whether this minutes is public or not", property: :visible
15
+
16
+ field :createdAt, Decidim::Core::DateTimeType do
17
+ description "The date and time this minutes was created"
18
+ property :created_at
19
+ end
20
+ field :updatedAt, Decidim::Core::DateTimeType do
21
+ description "The date and time this minutes was updated"
22
+ property :updated_at
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Meetings
5
+ ServiceType = GraphQL::ObjectType.define do
6
+ name "MeetingService"
7
+ description "A meeting service"
8
+
9
+ field :title, Decidim::Core::TranslatedFieldType, "The title for the service"
10
+ field :description, Decidim::Core::TranslatedFieldType, "The description for the service"
11
+ end
12
+ end
13
+ end
@@ -1,13 +1,13 @@
1
- <button class="button button--title secondary light share-link text-center calendar" data-open="calendarShare">
1
+ <button class="button button--title share-link text-center calendar" data-open="calendarShare">
2
2
  <%= t(".export_calendar") %>
3
- <%= icon "share", class: "icon--after" %>
3
+ <%= icon "share", class: "icon--after", role: "img", "aria-hidden": true %>
4
4
  </button>
5
5
  <div class="reveal" id="calendarShare" data-reveal>
6
6
  <div class="reveal__header">
7
- <h3 class="reveal__title"><%= t(".calendar_url") %>:</h3>
7
+ <h2 class="reveal__title"><%= t(".calendar_url") %>:</h2>
8
8
  <button class="close-button" data-close aria-label="<%= t(".close_window") %>" type="button">
9
9
  <span aria-hidden="true">&times;</span>
10
10
  </button>
11
11
  </div>
12
- <input type="text" value="<%= "#{path}" %>" readonly>
12
+ <input type="text" value="<%= "#{path}" %>" readonly title="<%= t(".calendar_url") %>">
13
13
  </div>
@@ -45,8 +45,8 @@
45
45
  <%= search_field_tag :q, @query,label: false, class: "input-group-field", placeholder: t(".search") %>
46
46
  <%= hidden_field_tag :state, @state %>
47
47
  <div class="input-group-button">
48
- <button type="submit" class="button button--muted">
49
- <%= icon "magnifying-glass", aria_label: t(".search") %>
48
+ <button type="submit" class="button">
49
+ <%= icon "magnifying-glass", aria_label: t(".search"), role: "img" %>
50
50
  </button>
51
51
  </div>
52
52
  </div>
@@ -22,12 +22,7 @@
22
22
  </div>
23
23
  </div>
24
24
  <div class="row column">
25
- <% if @form.proposals %>
26
- <%= form.select :proposal_ids,
27
- @form.proposals.order(title: :asc).map{|proposal| [decidim_html_escape(present(proposal).title), proposal.id]},
28
- { include_blank: true },
29
- { multiple: true, class: "chosen-select" } %>
30
- <% end %>
25
+ <%= proposals_picker(form, :proposals, proposals_picker_meeting_meeting_closes_path(meeting)) %>
31
26
  </div>
32
27
  </div>
33
28
  </div>
@@ -0,0 +1 @@
1
+ <%= cell "decidim/proposals/proposals_picker", current_component %>
@@ -13,14 +13,17 @@
13
13
 
14
14
  <div class="row column">
15
15
  <%= form.text_field :address %>
16
+ <p class="help-text"><%= t(".address_help") %></p>
16
17
  </div>
17
18
 
18
19
  <div class="row column">
19
20
  <%= form.translated :text_area, :location %>
21
+ <p class="help-text"><%= t(".location_help") %></p>
20
22
  </div>
21
23
 
22
24
  <div class="row column">
23
25
  <%= form.translated :text_area, :location_hints %>
26
+ <p class="help-text"><%= t(".location_hints_help") %></p>
24
27
  </div>
25
28
 
26
29
  <div class="row">
@@ -40,7 +43,7 @@
40
43
  <% end %>
41
44
 
42
45
  <div class="columns xlarge-6">
43
- <%= form.categories_select :decidim_category_id, current_participatory_space.categories, prompt: "", disable_parents: false %>
46
+ <%= form.categories_select :decidim_category_id, current_participatory_space.categories, include_blank: "", disable_parents: false %>
44
47
  </div>
45
48
  </div>
46
49
 
@@ -77,7 +77,22 @@
77
77
  <%= resource_permissions_link(meeting) %>
78
78
 
79
79
  <% if allowed_to? :destroy, :meeting, meeting: meeting %>
80
- <%= icon_link_to "circle-x", meeting_path(meeting), t("actions.destroy", scope: "decidim.meetings"), method: :delete, class: "action-icon--remove", data: { confirm: t("actions.confirm_destroy", scope: "decidim.meetings") } %>
80
+ <% if present(meeting).authored_proposals.empty? %>
81
+ <%= icon_link_to "circle-x", meeting_path(meeting), t("actions.destroy", scope: "decidim.meetings"), method: :delete, class: "action-icon--remove", data: { confirm: t("actions.confirm_destroy", scope: "decidim.meetings") } %>
82
+ <% else %>
83
+ <%=
84
+ content_tag(:button,
85
+ class: ["action-icon", "action-icon--remove", "destroy-meeting-alert"],
86
+ "data-invalid-destroy-message" => t("actions.invalid_destroy.proposals_count", count: present(meeting).authored_proposals.size, scope: "decidim.meetings"),
87
+ "data-proposal-titles" => present(meeting).formatted_proposals_titles) do
88
+ content_tag(:span,
89
+ data: { tooltip: true, disable_hover: false, click_open: false },
90
+ title: t("actions.destroy", scope: "decidim.meetings")) do
91
+ icon("circle-x")
92
+ end
93
+ end
94
+ %>
95
+ <% end %>
81
96
  <% end %>
82
97
  </td>
83
98
  </tr>
@@ -88,3 +103,5 @@
88
103
  </div>
89
104
  </div>
90
105
  </div>
106
+
107
+ <%= javascript_include_tag "decidim/meetings/admin/destroy_meeting_alert" %>