decidim-meetings 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/config/decidim_meetings_manifest.js +2 -0
- data/app/assets/javascripts/decidim/meetings/map.js.es6.erb +92 -0
- data/app/assets/stylesheets/decidim/meetings/map.css +1 -0
- data/app/commands/decidim/meetings/admin/close_meeting.rb +53 -0
- data/app/commands/decidim/meetings/admin/create_meeting.rb +15 -3
- data/app/commands/decidim/meetings/admin/update_meeting.rb +15 -3
- data/app/controllers/decidim/meetings/admin/application_controller.rb +9 -0
- data/app/controllers/decidim/meetings/admin/attachments_controller.rb +29 -0
- data/app/controllers/decidim/meetings/admin/meeting_closes_controller.rb +38 -0
- data/app/controllers/decidim/meetings/admin/meetings_controller.rb +0 -12
- data/app/controllers/decidim/meetings/meetings_controller.rb +11 -9
- data/app/forms/decidim/meetings/admin/close_meeting_form.rb +31 -0
- data/app/forms/decidim/meetings/admin/meeting_form.rb +0 -2
- data/app/helpers/decidim/meetings/admin/application_helper.rb +12 -0
- data/app/helpers/decidim/meetings/application_helper.rb +1 -0
- data/app/helpers/decidim/meetings/map_helper.rb +46 -0
- data/app/models/decidim/meetings/meeting.rb +11 -15
- data/app/services/decidim/meetings/meeting_search.rb +0 -1
- data/app/services/decidim/meetings/static_map_generator.rb +50 -0
- data/app/views/decidim/meetings/admin/meeting_closes/_form.html.erb +23 -0
- data/app/views/decidim/meetings/admin/meeting_closes/edit.html.erb +9 -0
- data/app/views/decidim/meetings/admin/meetings/_form.html.erb +2 -6
- data/app/views/decidim/meetings/admin/meetings/index.html.erb +14 -0
- data/app/views/decidim/meetings/meetings/_datetime.html.erb +8 -0
- data/app/views/decidim/meetings/meetings/_filters.html.erb +2 -2
- data/app/views/decidim/meetings/meetings/_filters_small_view.html.erb +18 -0
- data/app/views/decidim/meetings/meetings/_linked_meetings.html.erb +22 -0
- data/app/views/decidim/meetings/meetings/_meetings.html.erb +3 -10
- data/app/views/decidim/meetings/meetings/index.html.erb +42 -0
- data/app/views/decidim/meetings/meetings/index.js.erb +6 -0
- data/app/views/decidim/meetings/meetings/show.html.erb +33 -7
- data/config/i18n-tasks.yml +2 -0
- data/config/locales/ca.yml +37 -4
- data/config/locales/en.yml +34 -1
- data/config/locales/es.yml +36 -3
- data/db/migrate/20170110142105_close_a_meeting.rb +9 -0
- data/db/migrate/20170123151650_add_latitude_and_longitude_to_meetings.rb +6 -0
- data/db/migrate/20170129153716_remove_short_description_from_meetings.rb +5 -0
- data/lib/decidim/meetings/admin_engine.rb +31 -1
- data/lib/decidim/meetings/feature.rb +20 -6
- data/lib/decidim/meetings/list_engine.rb +10 -1
- data/lib/decidim/meetings/seeds/Exampledocument.pdf +0 -0
- data/lib/decidim/meetings/seeds/city.jpeg +0 -0
- data/lib/decidim/meetings/test/factories.rb +23 -0
- metadata +125 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 39ecff3ff25e1f270d3bcd1b057d2f6035179297
|
4
|
+
data.tar.gz: a9796345f56085b0bf6613ec26b83823fb8e1652
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 23ab8448060b0e8b10c0f079a31ded9cda519842ca798c0e5c42a4fb17acd5b9b5ce73c9ce4a9d0b5c66dabc3899fe4e5a78065da5709b3698a7de383b3b1f5b
|
7
|
+
data.tar.gz: 37d206c6c7ff80a8d82416233c6a30a2c9f868c6acff8ab5d6a3b2f0a517ab394d9c56fc3b8ad50f3c53bb50ba70616e511051f41c8cd022c324f322607733b9
|
@@ -0,0 +1,92 @@
|
|
1
|
+
// = require leaflet
|
2
|
+
// = require leaflet-tilelayer-here
|
3
|
+
// = require leaflet-svg-icon
|
4
|
+
// = require jquery-tmpl
|
5
|
+
// = require_self
|
6
|
+
|
7
|
+
/* globals L */
|
8
|
+
|
9
|
+
L.DivIcon.SVGIcon.DecidimIcon = L.DivIcon.SVGIcon.extend({
|
10
|
+
options: {
|
11
|
+
fillColor: '#ef604d',
|
12
|
+
opacity: 0
|
13
|
+
},
|
14
|
+
_createPathDescription: function() {
|
15
|
+
return 'M14 1.17a11.685 11.685 0 0 0-11.685 11.685c0 11.25 10.23 20.61 10.665 21a1.5 1.5 0 0 0 2.025 0c0.435-.435 10.665-9.81 10.665-21A11.685 11.685 0 0 0 14 1.17Zm0 17.415A5.085 5.085 0 1 1 19.085 13.5 5.085 5.085 0 0 1 14 18.585Z';
|
16
|
+
},
|
17
|
+
_createCircle: function() {
|
18
|
+
return ""
|
19
|
+
}
|
20
|
+
});
|
21
|
+
|
22
|
+
const popupTemplateId = 'meeting-popup';
|
23
|
+
$.template('meeting-popup', $(`#${popupTemplateId}`).html());
|
24
|
+
|
25
|
+
const addMarkers = (meetingsData, map) => {
|
26
|
+
const bounds = new L.LatLngBounds(meetingsData.map((meeting) => [meeting.latitude, meeting.longitude]));
|
27
|
+
|
28
|
+
meetingsData.forEach((meeting) => {
|
29
|
+
let marker = L.marker([meeting.latitude, meeting.longitude], {
|
30
|
+
icon: new L.DivIcon.SVGIcon.DecidimIcon()
|
31
|
+
}).addTo(map);
|
32
|
+
let node = document.createElement('div');
|
33
|
+
|
34
|
+
$.tmpl('meeting-popup', meeting).appendTo(node);
|
35
|
+
|
36
|
+
marker.bindPopup(node, {
|
37
|
+
maxwidth: 640,
|
38
|
+
minWidth: 500,
|
39
|
+
keepInView: true,
|
40
|
+
className: 'map-info'
|
41
|
+
}).openPopup();
|
42
|
+
});
|
43
|
+
|
44
|
+
map.fitBounds(bounds, { padding: [100, 100] });
|
45
|
+
};
|
46
|
+
|
47
|
+
const loadMap = (mapId, meetingsData) => {
|
48
|
+
const { hereAppId, hereAppCode } = window.DecidimMeetings.mapConfiguration;
|
49
|
+
|
50
|
+
if (window.DecidimMeetings.currentMap) {
|
51
|
+
window.DecidimMeetings.currentMap.remove();
|
52
|
+
window.DecidimMeetings.currentMap = null;
|
53
|
+
}
|
54
|
+
|
55
|
+
const map = L.map(mapId);
|
56
|
+
|
57
|
+
L.tileLayer.here({
|
58
|
+
appId: hereAppId,
|
59
|
+
appCode: hereAppCode,
|
60
|
+
}).addTo(map);
|
61
|
+
|
62
|
+
if (meetingsData.length > 0) {
|
63
|
+
addMarkers(meetingsData, map);
|
64
|
+
} else {
|
65
|
+
map.fitWorld();
|
66
|
+
}
|
67
|
+
|
68
|
+
map.scrollWheelZoom.disable();
|
69
|
+
|
70
|
+
return map;
|
71
|
+
};
|
72
|
+
|
73
|
+
window.DecidimMeetings = {
|
74
|
+
loadMap,
|
75
|
+
currentMap: null,
|
76
|
+
mapConfiguration: {}
|
77
|
+
};
|
78
|
+
|
79
|
+
$(() => {
|
80
|
+
const mapId = 'meetings-map';
|
81
|
+
const $map = $(`#${mapId}`);
|
82
|
+
|
83
|
+
const meetingsData = $map.data('meetings');
|
84
|
+
const hereAppId = $map.data('here-app-id');
|
85
|
+
const hereAppCode = $map.data('here-app-code');
|
86
|
+
|
87
|
+
window.DecidimMeetings.mapConfiguration = { hereAppId, hereAppCode };
|
88
|
+
|
89
|
+
if ($map.length > 0) {
|
90
|
+
window.DecidimMeetings.currentMap = loadMap(mapId, meetingsData);
|
91
|
+
}
|
92
|
+
});
|
@@ -0,0 +1 @@
|
|
1
|
+
/* = require leaflet */
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Decidim
|
3
|
+
module Meetings
|
4
|
+
module Admin
|
5
|
+
# This command is executed when the user closes a Meeting from the admin
|
6
|
+
# panel.
|
7
|
+
class CloseMeeting < Rectify::Command
|
8
|
+
# Initializes a CloseMeeting Command.
|
9
|
+
#
|
10
|
+
# form - The form from which to get the data.
|
11
|
+
# meeting - The current instance of the page to be closed.
|
12
|
+
def initialize(form, meeting)
|
13
|
+
@form = form
|
14
|
+
@meeting = meeting
|
15
|
+
end
|
16
|
+
|
17
|
+
# Closes the meeting if valid.
|
18
|
+
#
|
19
|
+
# Broadcasts :ok if successful, :invalid otherwise.
|
20
|
+
def call
|
21
|
+
return broadcast(:invalid) if @form.invalid?
|
22
|
+
|
23
|
+
transaction do
|
24
|
+
close_meeting
|
25
|
+
link_proposals
|
26
|
+
end
|
27
|
+
|
28
|
+
broadcast(:ok)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def close_meeting
|
34
|
+
@meeting.update_attributes!(
|
35
|
+
closing_report: @form.closing_report,
|
36
|
+
attendees_count: @form.attendees_count,
|
37
|
+
contributions_count: @form.contributions_count,
|
38
|
+
attending_organizations: @form.attending_organizations,
|
39
|
+
closed_at: @form.closed_at
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
def proposals
|
44
|
+
@meeting.sibling_scope(:proposals).where(id: @form.proposal_ids)
|
45
|
+
end
|
46
|
+
|
47
|
+
def link_proposals
|
48
|
+
@meeting.link_resources(proposals, "proposals_from_meeting")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -15,18 +15,20 @@ module Decidim
|
|
15
15
|
def call
|
16
16
|
return broadcast(:invalid) if @form.invalid?
|
17
17
|
|
18
|
+
build_meeting
|
19
|
+
return broadcast(:invalid) if Decidim.geocoder.present? && !geocode_meeting
|
18
20
|
create_meeting
|
21
|
+
|
19
22
|
broadcast(:ok)
|
20
23
|
end
|
21
24
|
|
22
25
|
private
|
23
26
|
|
24
|
-
def
|
25
|
-
Meeting.
|
27
|
+
def build_meeting
|
28
|
+
@meeting = Meeting.new(
|
26
29
|
scope: @form.scope,
|
27
30
|
category: @form.category,
|
28
31
|
title: @form.title,
|
29
|
-
short_description: @form.short_description,
|
30
32
|
description: @form.description,
|
31
33
|
end_time: @form.end_time,
|
32
34
|
start_time: @form.start_time,
|
@@ -36,6 +38,16 @@ module Decidim
|
|
36
38
|
feature: @form.current_feature
|
37
39
|
)
|
38
40
|
end
|
41
|
+
|
42
|
+
def geocode_meeting
|
43
|
+
result = @meeting.geocode
|
44
|
+
@form.errors.add :address, :invalid unless result
|
45
|
+
result
|
46
|
+
end
|
47
|
+
|
48
|
+
def create_meeting
|
49
|
+
@meeting.save!
|
50
|
+
end
|
39
51
|
end
|
40
52
|
end
|
41
53
|
end
|
@@ -20,18 +20,20 @@ module Decidim
|
|
20
20
|
def call
|
21
21
|
return broadcast(:invalid) if @form.invalid?
|
22
22
|
|
23
|
+
change_meeting
|
24
|
+
return broadcast(:invalid) if Decidim.geocoder.present? && @meeting.address_changed? && !geocode_meeting
|
23
25
|
update_meeting
|
26
|
+
|
24
27
|
broadcast(:ok)
|
25
28
|
end
|
26
29
|
|
27
30
|
private
|
28
31
|
|
29
|
-
def
|
30
|
-
@meeting.
|
32
|
+
def change_meeting
|
33
|
+
@meeting.assign_attributes(
|
31
34
|
scope: @form.scope,
|
32
35
|
category: @form.category,
|
33
36
|
title: @form.title,
|
34
|
-
short_description: @form.short_description,
|
35
37
|
description: @form.description,
|
36
38
|
end_time: @form.end_time,
|
37
39
|
start_time: @form.start_time,
|
@@ -40,6 +42,16 @@ module Decidim
|
|
40
42
|
location_hints: @form.location_hints
|
41
43
|
)
|
42
44
|
end
|
45
|
+
|
46
|
+
def geocode_meeting
|
47
|
+
result = @meeting.geocode
|
48
|
+
@form.errors.add :address, :invalid unless result
|
49
|
+
result
|
50
|
+
end
|
51
|
+
|
52
|
+
def update_meeting
|
53
|
+
@meeting.save!
|
54
|
+
end
|
43
55
|
end
|
44
56
|
end
|
45
57
|
end
|
@@ -8,6 +8,15 @@ module Decidim
|
|
8
8
|
# Note that it inherits from `Decidim::Features::BaseController`, which
|
9
9
|
# override its layout and provide all kinds of useful methods.
|
10
10
|
class ApplicationController < Decidim::Admin::Features::BaseController
|
11
|
+
helper_method :meetings, :meeting
|
12
|
+
|
13
|
+
def meetings
|
14
|
+
@meetings ||= Meeting.where(feature: current_feature)
|
15
|
+
end
|
16
|
+
|
17
|
+
def meeting
|
18
|
+
@meeting ||= meetings.find(params[:id])
|
19
|
+
end
|
11
20
|
end
|
12
21
|
end
|
13
22
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Decidim
|
3
|
+
module Meetings
|
4
|
+
module Admin
|
5
|
+
# Controller that allows managing all the attachments for a participatory
|
6
|
+
# process.
|
7
|
+
#
|
8
|
+
class AttachmentsController < Admin::ApplicationController
|
9
|
+
include Decidim::Admin::Concerns::HasAttachments
|
10
|
+
|
11
|
+
def after_destroy_path
|
12
|
+
meetings_path
|
13
|
+
end
|
14
|
+
|
15
|
+
def attached_to
|
16
|
+
meeting
|
17
|
+
end
|
18
|
+
|
19
|
+
def meeting
|
20
|
+
@meeting ||= meetings.find(params[:meeting_id])
|
21
|
+
end
|
22
|
+
|
23
|
+
def authorization_object
|
24
|
+
meeting.feature
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Decidim
|
3
|
+
module Meetings
|
4
|
+
module Admin
|
5
|
+
# This controller allows an admin to manage meetings from a Participatory Process
|
6
|
+
class MeetingClosesController < Admin::ApplicationController
|
7
|
+
helper ResourceHelper
|
8
|
+
helper_method :meeting
|
9
|
+
|
10
|
+
def edit
|
11
|
+
@form = form(CloseMeetingForm).from_model(meeting)
|
12
|
+
end
|
13
|
+
|
14
|
+
def update
|
15
|
+
@form = form(CloseMeetingForm).from_params(params.merge(proposals: meeting.sibling_scope(:proposals)))
|
16
|
+
|
17
|
+
CloseMeeting.call(@form, meeting) do
|
18
|
+
on(:ok) do
|
19
|
+
flash[:notice] = I18n.t("meetings.close.success", scope: "decidim.meetings.admin")
|
20
|
+
redirect_to meetings_path
|
21
|
+
end
|
22
|
+
|
23
|
+
on(:invalid) do
|
24
|
+
flash.now[:alert] = I18n.t("meetings.close.invalid", scope: "decidim.meetings.admin")
|
25
|
+
render action: "edit"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def meeting
|
33
|
+
@meeting ||= Meeting.where(feature: current_feature).find(params[:id])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -4,8 +4,6 @@ module Decidim
|
|
4
4
|
module Admin
|
5
5
|
# This controller allows an admin to manage meetings from a Participatory Process
|
6
6
|
class MeetingsController < Admin::ApplicationController
|
7
|
-
helper_method :meetings
|
8
|
-
|
9
7
|
def new
|
10
8
|
@form = form(MeetingForm).instance
|
11
9
|
end
|
@@ -53,16 +51,6 @@ module Decidim
|
|
53
51
|
|
54
52
|
redirect_to meetings_path
|
55
53
|
end
|
56
|
-
|
57
|
-
private
|
58
|
-
|
59
|
-
def meetings
|
60
|
-
@meetings ||= Meeting.where(feature: current_feature)
|
61
|
-
end
|
62
|
-
|
63
|
-
def meeting
|
64
|
-
@meeting ||= meetings.find(params[:id])
|
65
|
-
end
|
66
54
|
end
|
67
55
|
end
|
68
56
|
end
|
@@ -6,14 +6,23 @@ module Decidim
|
|
6
6
|
class MeetingsController < Decidim::Meetings::ApplicationController
|
7
7
|
include FilterResource
|
8
8
|
|
9
|
-
helper_method :meetings, :meeting
|
9
|
+
helper_method :meetings, :geocoded_meetings, :meeting
|
10
10
|
|
11
11
|
def index; end
|
12
12
|
|
13
|
+
def static_map
|
14
|
+
@meeting = Meeting.where(feature: current_feature).find(params[:id])
|
15
|
+
send_data StaticMapGenerator.new(@meeting).data, type: "image/jpeg", disposition: "inline"
|
16
|
+
end
|
17
|
+
|
13
18
|
private
|
14
19
|
|
15
20
|
def meetings
|
16
|
-
@meetings ||= search.results
|
21
|
+
@meetings ||= search.results.page(params[:page]).per(12)
|
22
|
+
end
|
23
|
+
|
24
|
+
def geocoded_meetings
|
25
|
+
@geocoded_meetings ||= search.results.select(&:geocoded?)
|
17
26
|
end
|
18
27
|
|
19
28
|
def meeting
|
@@ -24,13 +33,6 @@ module Decidim
|
|
24
33
|
MeetingSearch
|
25
34
|
end
|
26
35
|
|
27
|
-
def default_search_params
|
28
|
-
{
|
29
|
-
page: params[:page],
|
30
|
-
per_page: 12
|
31
|
-
}
|
32
|
-
end
|
33
|
-
|
34
36
|
def default_filter_params
|
35
37
|
{
|
36
38
|
order_start_time: "asc",
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Decidim
|
3
|
+
module Meetings
|
4
|
+
module Admin
|
5
|
+
# This class holds a Form to close a meeting from Decidim's admin panel.
|
6
|
+
class CloseMeetingForm < Decidim::Form
|
7
|
+
include TranslatableAttributes
|
8
|
+
|
9
|
+
translatable_attribute :closing_report, String
|
10
|
+
attribute :attendees_count, Integer, default: 0
|
11
|
+
attribute :contributions_count, Integer, default: 0
|
12
|
+
attribute :attending_organizations, String
|
13
|
+
attribute :proposal_ids, Array[Integer]
|
14
|
+
attribute :proposals
|
15
|
+
attribute :closed_at, DateTime, default: ->(_form, _attribute) { Time.current }
|
16
|
+
|
17
|
+
validates :closing_report, translatable_presence: true
|
18
|
+
validates :attendees_count, :contributions_count, presence: true, numericality: { greater_than_or_equal_to: 0 }
|
19
|
+
validates :attending_organizations, presence: true
|
20
|
+
|
21
|
+
# Private: Gets the proposals from the meeting and injects them to the form.
|
22
|
+
#
|
23
|
+
# Returns nothing.
|
24
|
+
def map_model(model)
|
25
|
+
self.proposal_ids = model.linked_resources(:proposals, "proposals_from_meeting").pluck(:id)
|
26
|
+
self.proposals = model.sibling_scope(:proposals)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -7,7 +7,6 @@ module Decidim
|
|
7
7
|
include TranslatableAttributes
|
8
8
|
|
9
9
|
translatable_attribute :title, String
|
10
|
-
translatable_attribute :short_description, String
|
11
10
|
translatable_attribute :description, String
|
12
11
|
translatable_attribute :location, String
|
13
12
|
translatable_attribute :location_hints, String
|
@@ -18,7 +17,6 @@ module Decidim
|
|
18
17
|
attribute :decidim_category_id, Integer
|
19
18
|
|
20
19
|
validates :title, translatable_presence: true
|
21
|
-
validates :short_description, translatable_presence: true
|
22
20
|
validates :description, translatable_presence: true
|
23
21
|
validates :location, translatable_presence: true
|
24
22
|
validates :address, presence: true
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Decidim
|
3
|
+
module Meetings
|
4
|
+
# This helper include some methods for rendering meetings static and dynamic maps.
|
5
|
+
module MapHelper
|
6
|
+
# Renders a link to openstreetmaps with the meeting latitude and longitude.
|
7
|
+
# The link's content is a static map image.
|
8
|
+
#
|
9
|
+
# meeting - A Decidim::Meetings::Meeting object
|
10
|
+
# options - An optional hash of options (default: { zoom: 17 })
|
11
|
+
# * zoom: A number to represent the zoom value of the map
|
12
|
+
def static_map_link(meeting, options = {})
|
13
|
+
if meeting.geocoded?
|
14
|
+
zoom = options[:zoom] || 17
|
15
|
+
latitude = meeting.latitude
|
16
|
+
longitude = meeting.longitude
|
17
|
+
|
18
|
+
map_url = "https://www.openstreetmap.org/?mlat=#{latitude}&mlon=#{longitude}#map=#{zoom}/#{latitude}/#{longitude}"
|
19
|
+
|
20
|
+
link_to map_url, target: "_blank" do
|
21
|
+
image_tag decidim_meetings.static_map_meeting_path(feature_id: meeting.feature,
|
22
|
+
participatory_process_id: meeting.feature.participatory_process,
|
23
|
+
id: meeting)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Serialize a collection of geocoded meetings to be used by the dynamic map component
|
29
|
+
#
|
30
|
+
# geocoded_meetings - A collection of geocoded meetings
|
31
|
+
def meetings_data_for_map(geocoded_meetings)
|
32
|
+
geocoded_meetings.map do |meeting|
|
33
|
+
meeting.slice(:latitude, :longitude, :address).merge(title: translated_attribute(meeting.title),
|
34
|
+
description: translated_attribute(meeting.description),
|
35
|
+
startTimeDay: l(meeting.start_time, format: "%d"),
|
36
|
+
startTimeMonth: l(meeting.start_time, format: "%B"),
|
37
|
+
startTime: "#{meeting.start_time.strftime("%H:%M")} - #{meeting.end_time.strftime("%H:%M")}",
|
38
|
+
icon: icon("meetings", width: 40, height: 70, remove_icon_class: true),
|
39
|
+
location: translated_attribute(meeting.location),
|
40
|
+
locationHints: translated_attribute(meeting.location_hints),
|
41
|
+
link: meeting_path(meeting))
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -1,28 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Decidim
|
3
4
|
module Meetings
|
4
5
|
# The data store for a Meeting in the Decidim::Meetings component. It stores a
|
5
6
|
# title, description and any other useful information to render a custom meeting.
|
6
7
|
class Meeting < Meetings::ApplicationRecord
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
include Decidim::Resourceable
|
9
|
+
include Decidim::HasAttachments
|
10
|
+
include Decidim::HasFeature
|
11
|
+
include Decidim::HasScope
|
12
|
+
include Decidim::HasCategory
|
12
13
|
|
13
|
-
|
14
|
-
validate :category_belongs_to_organization
|
14
|
+
feature_manifest_name "meetings"
|
15
15
|
|
16
|
-
|
16
|
+
validates :title, presence: true
|
17
17
|
|
18
|
-
|
19
|
-
return unless scope
|
20
|
-
errors.add(:scope, :invalid) unless feature.scopes.where(id: scope.id).exists?
|
21
|
-
end
|
18
|
+
geocoded_by :address
|
22
19
|
|
23
|
-
def
|
24
|
-
|
25
|
-
errors.add(:category, :invalid) unless feature.categories.where(id: category.id).exists?
|
20
|
+
def closed?
|
21
|
+
closed_at.present?
|
26
22
|
end
|
27
23
|
end
|
28
24
|
end
|
@@ -18,7 +18,6 @@ module Decidim
|
|
18
18
|
query
|
19
19
|
.where(localized_search_text_in(:title), text: "%#{search_text}%")
|
20
20
|
.or(query.where(localized_search_text_in(:description), text: "%#{search_text}%"))
|
21
|
-
.or(query.where(localized_search_text_in(:short_description), text: "%#{search_text}%"))
|
22
21
|
end
|
23
22
|
|
24
23
|
# Handle the order_start_time filter
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "httparty"
|
3
|
+
|
4
|
+
module Decidim
|
5
|
+
module Meetings
|
6
|
+
# This class generates a url to create a static map image for a geocoded meeting
|
7
|
+
class StaticMapGenerator
|
8
|
+
BASE_HOST = "image.maps.cit.api.here.com"
|
9
|
+
BASE_PATH = "/mia/1.6/mapview"
|
10
|
+
|
11
|
+
def initialize(meeting, options = {})
|
12
|
+
@meeting = meeting
|
13
|
+
@options = options
|
14
|
+
|
15
|
+
@options[:zoom] ||= 15
|
16
|
+
@options[:width] ||= 120
|
17
|
+
@options[:height] ||= 120
|
18
|
+
end
|
19
|
+
|
20
|
+
def data
|
21
|
+
return if Decidim.geocoder.nil?
|
22
|
+
|
23
|
+
Rails.cache.fetch(@meeting.cache_key) do
|
24
|
+
request = HTTParty.get(uri)
|
25
|
+
request.body
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def uri
|
32
|
+
params = {
|
33
|
+
c: "#{@meeting.latitude}, #{@meeting.longitude}",
|
34
|
+
z: @options[:zoom],
|
35
|
+
w: @options[:width],
|
36
|
+
h: @options[:height],
|
37
|
+
f: "1",
|
38
|
+
app_id: Decidim.geocoder&.fetch(:here_app_id),
|
39
|
+
app_code: Decidim.geocoder&.fetch(:here_app_code)
|
40
|
+
}
|
41
|
+
|
42
|
+
uri = URI.parse("https://#{BASE_HOST}#{BASE_PATH}").tap do |uri|
|
43
|
+
uri.query = URI.encode_www_form params
|
44
|
+
end
|
45
|
+
|
46
|
+
uri
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<div class="field">
|
2
|
+
<%= form.translated :text_area, :closing_report, autofocus: true, rows: 15 %>
|
3
|
+
</div>
|
4
|
+
|
5
|
+
<div class="field">
|
6
|
+
<%= form.text_area :attending_organizations, rows: 5 %>
|
7
|
+
</div>
|
8
|
+
|
9
|
+
<div class="field">
|
10
|
+
<%= form.number_field :attendees_count, min: 0 %>
|
11
|
+
</div>
|
12
|
+
|
13
|
+
<div class="field">
|
14
|
+
<%= form.number_field :contributions_count, min: 0 %>
|
15
|
+
</div>
|
16
|
+
|
17
|
+
<% if @form.proposals %>
|
18
|
+
<%= form.select :proposal_ids,
|
19
|
+
@form.proposals.order("title ASC").pluck(:title, :id),
|
20
|
+
{ include_blank: true },
|
21
|
+
{ multiple: true, class: "chosen-select" }
|
22
|
+
%>
|
23
|
+
<% end %>
|
@@ -3,11 +3,11 @@
|
|
3
3
|
</div>
|
4
4
|
|
5
5
|
<div class="field" >
|
6
|
-
<%= form.translated :editor, :
|
6
|
+
<%= form.translated :editor, :description %>
|
7
7
|
</div>
|
8
8
|
|
9
9
|
<div class="field" >
|
10
|
-
<%= form.
|
10
|
+
<%= form.text_field :address %>
|
11
11
|
</div>
|
12
12
|
|
13
13
|
<div class="field" >
|
@@ -18,10 +18,6 @@
|
|
18
18
|
<%= form.translated :text_area, :location_hints %>
|
19
19
|
</div>
|
20
20
|
|
21
|
-
<div class="field" >
|
22
|
-
<%= form.text_field :address %>
|
23
|
-
</div>
|
24
|
-
|
25
21
|
<div class="field" >
|
26
22
|
<%= form.datetime_field :start_time %>
|
27
23
|
</div>
|