decidim-comparative_stats 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE-AGPLv3.txt +661 -0
- data/README.md +187 -0
- data/Rakefile +40 -0
- data/app/assets/config/admin/comparative_stats_manifest.css +4 -0
- data/app/assets/config/admin/comparative_stats_manifest.js +2 -0
- data/app/assets/config/comparative_stats_manifest.css +4 -0
- data/app/assets/config/comparative_stats_manifest.js +2 -0
- data/app/assets/images/bcn-logo.png +0 -0
- data/app/assets/images/decidim/comparative_stats/icon.svg +1 -0
- data/app/assets/images/platoniq-logo.png +0 -0
- data/app/assets/javascripts/decidim/comparative_stats/geocoded_events.js.es6 +94 -0
- data/app/assets/javascripts/decidim/comparative_stats/graphs.js.es6 +13 -0
- data/app/assets/stylesheets/decidim/comparative_stats/geocoded_events.scss +23 -0
- data/app/assets/stylesheets/decidim/comparative_stats/graphs.scss +6 -0
- data/app/assets/stylesheets/decidim/comparative_stats/widget.scss +8 -0
- data/app/cells/decidim/comparative_stats/metric_piecharts/show.erb +14 -0
- data/app/cells/decidim/comparative_stats/metric_piecharts_cell.rb +39 -0
- data/app/cells/decidim/comparative_stats/metric_timelines/show.erb +14 -0
- data/app/cells/decidim/comparative_stats/metric_timelines_cell.rb +23 -0
- data/app/cells/decidim/comparative_stats/participatory_processes_timeline/show.erb +55 -0
- data/app/cells/decidim/comparative_stats/participatory_processes_timeline_cell.rb +51 -0
- data/app/cells/decidim/comparative_stats/participatory_spaces_geocoded_events/show.erb +55 -0
- data/app/cells/decidim/comparative_stats/participatory_spaces_geocoded_events_cell.rb +108 -0
- data/app/commands/decidim/comparative_stats/admin/create_endpoint.rb +46 -0
- data/app/commands/decidim/comparative_stats/admin/destroy_endpoint.rb +43 -0
- data/app/commands/decidim/comparative_stats/admin/update_endpoint.rb +47 -0
- data/app/controllers/decidim/comparative_stats/admin/application_controller.rb +16 -0
- data/app/controllers/decidim/comparative_stats/admin/endpoints_controller.rb +83 -0
- data/app/controllers/decidim/comparative_stats/admin/graphs_controller.rb +16 -0
- data/app/controllers/decidim/comparative_stats/widgets_controller.rb +31 -0
- data/app/forms/decidim/comparative_stats/admin/endpoint_form.rb +26 -0
- data/app/helpers/decidim/comparative_stats/application_helper.rb +27 -0
- data/app/models/decidim/comparative_stats/application_record.rb +10 -0
- data/app/models/decidim/comparative_stats/endpoint.rb +22 -0
- data/app/permissions/decidim/comparative_stats/admin/permissions.rb +24 -0
- data/app/presenters/decidim/comparative_stats/admin_log/endpoint_presenter.rb +46 -0
- data/app/views/decidim/comparative_stats/admin/endpoints/_form.html.erb +7 -0
- data/app/views/decidim/comparative_stats/admin/endpoints/edit.html.erb +16 -0
- data/app/views/decidim/comparative_stats/admin/endpoints/index.html.erb +66 -0
- data/app/views/decidim/comparative_stats/admin/endpoints/new.html.erb +16 -0
- data/app/views/decidim/comparative_stats/admin/graphs/show.html.erb +15 -0
- data/app/views/decidim/comparative_stats/widgets/_all.html.erb +1 -0
- data/app/views/decidim/comparative_stats/widgets/_embed.html.erb +7 -0
- data/app/views/decidim/comparative_stats/widgets/_embed_modal.html.erb +27 -0
- data/app/views/decidim/comparative_stats/widgets/_global_stats.html.erb +4 -0
- data/app/views/decidim/comparative_stats/widgets/_global_stats_timeline.html.erb +4 -0
- data/app/views/decidim/comparative_stats/widgets/_processes_timeline.html.erb +4 -0
- data/app/views/decidim/comparative_stats/widgets/_spaces_geocoded_events.html.erb +5 -0
- data/app/views/decidim/comparative_stats/widgets/_tabs.html.erb +19 -0
- data/app/views/decidim/comparative_stats/widgets/show.html.erb +1 -0
- data/app/views/layouts/decidim/admin/comparative_stats.html.erb +28 -0
- data/app/views/layouts/decidim/comparative_stats/widget.html.erb +22 -0
- data/config/i18n-tasks.yml +10 -0
- data/config/locales/ca.yml +57 -0
- data/config/locales/cs.yml +57 -0
- data/config/locales/en.yml +64 -0
- data/config/locales/es.yml +57 -0
- data/db/migrate/20191219104548_create_decidim_comparative_stats_endpoints.rb +13 -0
- data/db/migrate/20200122072955_add_name_version_to_comparative_stats_endpoints.rb +8 -0
- data/db/migrate/20200130203914_rename_version_field_in_comparative_stats_endpoints.rb +7 -0
- data/db/seeds.rb +42 -0
- data/lib/decidim/comparative_stats.rb +22 -0
- data/lib/decidim/comparative_stats/admin.rb +10 -0
- data/lib/decidim/comparative_stats/admin_engine.rb +50 -0
- data/lib/decidim/comparative_stats/api_fetcher.rb +93 -0
- data/lib/decidim/comparative_stats/cached_http_adapter.rb +23 -0
- data/lib/decidim/comparative_stats/engine.rb +34 -0
- data/lib/decidim/comparative_stats/queries/global_events.graphql +84 -0
- data/lib/decidim/comparative_stats/queries/global_history_metrics.graphql +10 -0
- data/lib/decidim/comparative_stats/queries/global_metrics.graphql +6 -0
- data/lib/decidim/comparative_stats/queries/name_and_version.graphql +6 -0
- data/lib/decidim/comparative_stats/queries/participatory_processes.graphql +12 -0
- data/lib/decidim/comparative_stats/queries/v022/global_events.graphql +76 -0
- data/lib/decidim/comparative_stats/test/factories.rb +13 -0
- data/lib/decidim/comparative_stats/version.rb +10 -0
- data/vendor/assets/images/draw/layers-2x.png +0 -0
- data/vendor/assets/images/draw/layers.png +0 -0
- data/vendor/assets/images/draw/marker-icon-2x.png +0 -0
- data/vendor/assets/images/draw/marker-icon.png +0 -0
- data/vendor/assets/images/draw/marker-shadow.png +0 -0
- data/vendor/assets/images/draw/spritesheet-2x.png +0 -0
- data/vendor/assets/images/draw/spritesheet.png +0 -0
- data/vendor/assets/images/draw/spritesheet.svg +156 -0
- data/vendor/assets/images/images/layers-2x.png +0 -0
- data/vendor/assets/images/images/layers.png +0 -0
- data/vendor/assets/images/images/marker-icon-2x.png +0 -0
- data/vendor/assets/images/images/marker-icon.png +0 -0
- data/vendor/assets/images/images/marker-shadow.png +0 -0
- data/vendor/assets/javascripts/leaflet.js +5 -0
- metadata +234 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
<div class="row">
|
2
|
+
<% metrics.each do |name, metric| %>
|
3
|
+
<div class="column" style="padding: 1em">
|
4
|
+
<div class="card">
|
5
|
+
<div class="card-divider">
|
6
|
+
<%= title name %>
|
7
|
+
</div>
|
8
|
+
<div class="card-section">
|
9
|
+
<%= line_chart metric, id: "line_chart_#{name}" %>
|
10
|
+
</div>
|
11
|
+
</div>
|
12
|
+
</div>
|
13
|
+
<% end %>
|
14
|
+
</div>
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ComparativeStats
|
5
|
+
class MetricTimelinesCell < MetricPiechartsCell
|
6
|
+
def metrics
|
7
|
+
history = {}
|
8
|
+
endpoints.each do |endpoint|
|
9
|
+
endpoint.api.fetch_global_history_metrics.data.metrics.each do |item|
|
10
|
+
history[item.name] ||= []
|
11
|
+
history[item.name] << {
|
12
|
+
name: endpoint.name,
|
13
|
+
data: item.history.map do |i|
|
14
|
+
[i.key, i.value]
|
15
|
+
end.to_h
|
16
|
+
}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
history
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
<div class="row column full-height">
|
2
|
+
<%= timeline [], id: "participatoryProcessesChart", height: "100%" %>
|
3
|
+
</div>
|
4
|
+
<script>
|
5
|
+
(function() {
|
6
|
+
var rows = [];
|
7
|
+
<% timeline_graph.each do |row| %>
|
8
|
+
rows.push([
|
9
|
+
"<%= row[:name] %>",
|
10
|
+
"<%= row[:title] %>",
|
11
|
+
new Date("<%= row[:start_date] %>"),
|
12
|
+
new Date("<%= row[:end_date] %>")
|
13
|
+
]);
|
14
|
+
<% end %>
|
15
|
+
|
16
|
+
var drawChart = function() {
|
17
|
+
var dataTable = new google.visualization.DataTable();
|
18
|
+
dataTable.addColumn({ type: 'string', id: 'Platform' });
|
19
|
+
dataTable.addColumn({ type: 'string', id: 'Process' });
|
20
|
+
dataTable.addColumn({ type: 'date', id: 'Start' });
|
21
|
+
dataTable.addColumn({ type: 'date', id: 'End' });
|
22
|
+
dataTable.addRows(rows);
|
23
|
+
var chart = Chartkick.charts["participatoryProcessesChart"];
|
24
|
+
chart.getChartObject().draw(dataTable);
|
25
|
+
|
26
|
+
// hack the real height
|
27
|
+
var h = parseInt($("#participatoryProcessesChart div:first-child div:first-child div:first-child div svg").attr("height")) + 70;
|
28
|
+
chart.getChartObject().draw(dataTable, {
|
29
|
+
height: h,
|
30
|
+
// hAxis: {
|
31
|
+
// minValue: new Date(2019, 0, 0),
|
32
|
+
// maxValue: new Date(2020, 0, 0)
|
33
|
+
// },
|
34
|
+
width: "100%",
|
35
|
+
timeline: {
|
36
|
+
// showRowLabels: false,
|
37
|
+
rowLabelStyle: {
|
38
|
+
fontSize: 16
|
39
|
+
},
|
40
|
+
// showBarLabels: false
|
41
|
+
}
|
42
|
+
});
|
43
|
+
// extra svg tweaks
|
44
|
+
$('#participatoryProcessesChart div div div svg g:first text').attr({'x': 5, "text-anchor": "start", "font-weight": "bold"})
|
45
|
+
};
|
46
|
+
|
47
|
+
google.charts.setOnLoadCallback(drawChart);
|
48
|
+
|
49
|
+
// Rewdraw on tab appearance
|
50
|
+
$("[data-tabs]").on("change.zf.tabs", drawChart);
|
51
|
+
// redraw graph when window resize is completed
|
52
|
+
$(window).on('resizeEnd', drawChart);
|
53
|
+
|
54
|
+
}());
|
55
|
+
</script>
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "chartkick"
|
4
|
+
require "chartkick/helper"
|
5
|
+
|
6
|
+
module Decidim
|
7
|
+
module ComparativeStats
|
8
|
+
# This cell renders an graph with participatory processes
|
9
|
+
# the `model` is expected to be a collection of API endpoints
|
10
|
+
#
|
11
|
+
class ParticipatoryProcessesTimelineCell < Decidim::ViewModel
|
12
|
+
include Chartkick::Helper
|
13
|
+
|
14
|
+
def show
|
15
|
+
return unless model
|
16
|
+
|
17
|
+
render :show
|
18
|
+
end
|
19
|
+
|
20
|
+
def endpoints
|
21
|
+
model
|
22
|
+
end
|
23
|
+
|
24
|
+
def timeline_graph
|
25
|
+
rows = []
|
26
|
+
endpoints.each do |endpoint|
|
27
|
+
endpoint.api.fetch_participatory_processes.data.participatory_processes.each do |item|
|
28
|
+
next unless item.start_date
|
29
|
+
|
30
|
+
start_date = Date.parse(item.start_date)
|
31
|
+
end_date = Date.parse(item.end_date.presence || Date.current.end_of_year.to_s)
|
32
|
+
# let's not trust people writing proper ordered dates
|
33
|
+
start_date, end_date = end_date, start_date if start_date > end_date
|
34
|
+
rows << {
|
35
|
+
name: endpoint.name,
|
36
|
+
title: first_text(item.title.translations),
|
37
|
+
start_date: start_date,
|
38
|
+
end_date: end_date
|
39
|
+
}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
rows
|
43
|
+
end
|
44
|
+
|
45
|
+
def first_text(translations)
|
46
|
+
item = translations.find { |i| i.text.present? }
|
47
|
+
item&.text || ""
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
<template id="marker-popup-meeting">
|
2
|
+
<div class="map-info__content">
|
3
|
+
<h3>${title}</h3>
|
4
|
+
<div id="bodyContent">
|
5
|
+
<p>{{html description}}</p>
|
6
|
+
<div class="map__date-adress">
|
7
|
+
<div class="card__datetime">
|
8
|
+
<div class="card__datetime__date">
|
9
|
+
${startTimeDay} <span class="card__datetime__month">${startTimeMonth} ${startTimeYear}</span>
|
10
|
+
</div>
|
11
|
+
<div class="card__datetime__time">${starTime}</div>
|
12
|
+
</div>
|
13
|
+
<div class="address card__extra">
|
14
|
+
<div class="address__icon">{{html icon}}</div>
|
15
|
+
<div class="address__details">
|
16
|
+
<strong>{{html location}}</strong><br>
|
17
|
+
<span>${address}</span><br>
|
18
|
+
<span>{{html locationHints}}</span>
|
19
|
+
</div>
|
20
|
+
</div>
|
21
|
+
</div>
|
22
|
+
<div class="map-info__button">
|
23
|
+
<a href="${link}" class="button button--sc">
|
24
|
+
<%= t("decidim.meetings.meetings_map.view_meeting") %>
|
25
|
+
</a>
|
26
|
+
</div>
|
27
|
+
</div>
|
28
|
+
</div>
|
29
|
+
</template>
|
30
|
+
|
31
|
+
<template id="marker-popup-proposal">
|
32
|
+
<div class="map-info__content">
|
33
|
+
<h3>${title}</h3>
|
34
|
+
<div id="bodyContent">
|
35
|
+
<p>{{html body}}</p>
|
36
|
+
<div class="map__date-adress">
|
37
|
+
<div class="address card__extra">
|
38
|
+
<div class="address__icon">{{html icon}}</div>
|
39
|
+
<div class="address__details">
|
40
|
+
<span>${address}</span><br>
|
41
|
+
</div>
|
42
|
+
</div>
|
43
|
+
</div>
|
44
|
+
<div class="map-info__button">
|
45
|
+
<a href="${link}" class="button button--sc">
|
46
|
+
<%= t("decidim.proposals.proposals.index.view_proposal") %>
|
47
|
+
</a>
|
48
|
+
</div>
|
49
|
+
</div>
|
50
|
+
</div>
|
51
|
+
</template>
|
52
|
+
|
53
|
+
<div class="row column full-height">
|
54
|
+
<%= content_tag(:div, "", id: "geocoded_events", class: "map", data: { geocoded_events: geocoded_events }) %>
|
55
|
+
</div>
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ComparativeStats
|
5
|
+
# This cell renders a map with participatory spaces
|
6
|
+
# the `model` is spected to be a collection of API endpoints
|
7
|
+
class ParticipatorySpacesGeocodedEventsCell < Decidim::ViewModel
|
8
|
+
include Decidim::MapHelper
|
9
|
+
include Decidim::LayoutHelper
|
10
|
+
|
11
|
+
def show
|
12
|
+
return unless model
|
13
|
+
|
14
|
+
render :show
|
15
|
+
end
|
16
|
+
|
17
|
+
def endpoints
|
18
|
+
model
|
19
|
+
end
|
20
|
+
|
21
|
+
def geocoded_events
|
22
|
+
@events = {}
|
23
|
+
|
24
|
+
endpoints.each do |endpoint|
|
25
|
+
# skip endpoints under version 0.21
|
26
|
+
next unless endpoint.api.valid? "0.21"
|
27
|
+
|
28
|
+
@events[endpoint.id] = {
|
29
|
+
name: endpoint.name,
|
30
|
+
meetings: {},
|
31
|
+
proposals: {}
|
32
|
+
}
|
33
|
+
results = endpoint.api.fetch_global_events
|
34
|
+
next unless results.respond_to? :data
|
35
|
+
|
36
|
+
results.data.assemblies.each do |assembly|
|
37
|
+
assembly.components.each do |component|
|
38
|
+
if component.respond_to? :meetings
|
39
|
+
component.meetings.edges.each do |edge|
|
40
|
+
add_meeting(edge.node.to_h, endpoint, assembly, component, :assemblies)
|
41
|
+
end
|
42
|
+
elsif componet.respond_to? :proposals
|
43
|
+
component.proposals.edges.each do |edge|
|
44
|
+
add_proposal(edge.node.to_h, endpoint, assembly, component, :assemblies)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
results.data.participatory_processes.each do |participatory_process|
|
50
|
+
participatory_process.components.each do |component|
|
51
|
+
if component.respond_to? :meetings
|
52
|
+
component.meetings.edges.each do |edge|
|
53
|
+
add_meeting(edge.node.to_h, endpoint, participatory_process, component, :processes)
|
54
|
+
end
|
55
|
+
elsif component.respond_to? :proposals
|
56
|
+
component.proposals.edges.each do |edge|
|
57
|
+
add_proposal(edge.node.to_h, endpoint, participatory_process, component, :processes)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
@events.to_json
|
64
|
+
end
|
65
|
+
|
66
|
+
def first_translation(text)
|
67
|
+
return text unless text.is_a? Hash
|
68
|
+
|
69
|
+
translations = text["translations"]
|
70
|
+
if translations
|
71
|
+
item = translations.find { |i| i["text"].present? }
|
72
|
+
return item["text"] || "" if item
|
73
|
+
end
|
74
|
+
""
|
75
|
+
end
|
76
|
+
|
77
|
+
def add_proposal(proposal, endpoint, participatory_space, component, type)
|
78
|
+
@events[endpoint.id][:proposals]["#{type}_proposal_#{proposal["id"]}"] = {
|
79
|
+
latitude: proposal["coordinates"]["latitude"],
|
80
|
+
longitude: proposal["coordinates"]["longitude"],
|
81
|
+
address: proposal["address"],
|
82
|
+
title: first_translation(proposal["title"]),
|
83
|
+
body: truncate(first_translation(proposal["body"]), length: 100),
|
84
|
+
icon: icon("proposals", width: 40, height: 70, remove_icon_class: true),
|
85
|
+
link: endpoint.endpoint.remove("api") << "#{type}/#{participatory_space.slug}/f/#{component.id}/proposals/#{proposal["id"]}"
|
86
|
+
}
|
87
|
+
end
|
88
|
+
|
89
|
+
def add_meeting(meeting, endpoint, participatory_space, component, type)
|
90
|
+
@events[endpoint.id][:meetings]["#{type}_meeting_#{meeting["id"]}"] = {
|
91
|
+
latitude: meeting["coordinates"]["latitude"],
|
92
|
+
longitude: meeting["coordinates"]["longitude"],
|
93
|
+
address: meeting["address"],
|
94
|
+
title: first_translation(meeting["title"]),
|
95
|
+
# description: first_translation(meeting["description"]),
|
96
|
+
startTimeDay: l(meeting["startTime"].to_date, format: "%d"),
|
97
|
+
startTimeMonth: l(meeting["startTime"].to_date, format: "%B"),
|
98
|
+
startTimeYear: l(meeting["startTime"].to_date, format: "%Y"),
|
99
|
+
startTime: "#{meeting["startTime"].to_date.strftime("%H:%M")} - #{meeting["endTime"].to_date.strftime("%H:%M")}",
|
100
|
+
icon: icon("meetings", width: 40, height: 70, remove_icon_class: true),
|
101
|
+
location: first_translation(meeting["location"]),
|
102
|
+
locationHints: first_translation(meeting["location_hints"]),
|
103
|
+
link: endpoint.endpoint.remove("api") << "#{type}/#{participatory_space.slug}/f/#{component.id}/meetings/#{meeting["id"]}"
|
104
|
+
}
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ComparativeStats
|
5
|
+
module Admin
|
6
|
+
# A command with all the business logic when creating an endpoint
|
7
|
+
class CreateEndpoint < Rectify::Command
|
8
|
+
# Public: Initializes the command.
|
9
|
+
#
|
10
|
+
# form - A form object with the params.
|
11
|
+
def initialize(form)
|
12
|
+
@form = form
|
13
|
+
end
|
14
|
+
|
15
|
+
# Executes the command. Broadcasts these events:
|
16
|
+
#
|
17
|
+
# - :ok when everything is valid.
|
18
|
+
# - :invalid if the form wasn't valid and we couldn't proceed.
|
19
|
+
#
|
20
|
+
# Returns nothing.
|
21
|
+
def call
|
22
|
+
return broadcast(:invalid) if form.invalid?
|
23
|
+
|
24
|
+
create_endpoint
|
25
|
+
broadcast(:ok)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
attr_reader :form
|
31
|
+
|
32
|
+
def create_endpoint
|
33
|
+
Decidim.traceability.create!(
|
34
|
+
Decidim::ComparativeStats::Endpoint,
|
35
|
+
form.current_user,
|
36
|
+
endpoint: form.endpoint,
|
37
|
+
name: form.context.api.name_and_version.application_name,
|
38
|
+
api_version: form.context.api.name_and_version.version,
|
39
|
+
organization: form.current_organization,
|
40
|
+
active: form.active
|
41
|
+
)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ComparativeStats
|
5
|
+
module Admin
|
6
|
+
# A command with all the business logic when destroying an endpoint
|
7
|
+
class DestroyEndpoint < Rectify::Command
|
8
|
+
# Public: Initializes the command.
|
9
|
+
#
|
10
|
+
# form - A form object with the params.
|
11
|
+
def initialize(endpoint, current_user)
|
12
|
+
@endpoint = endpoint
|
13
|
+
@current_user = current_user
|
14
|
+
end
|
15
|
+
|
16
|
+
# Executes the command. Broadcasts these events:
|
17
|
+
#
|
18
|
+
# - :ok when everything is valid.
|
19
|
+
# - :invalid if the form wasn't valid and we couldn't proceed.
|
20
|
+
#
|
21
|
+
# Returns nothing.
|
22
|
+
def call
|
23
|
+
destroy_endpoint!
|
24
|
+
broadcast(:ok)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
attr_reader :endpoint, :current_user
|
30
|
+
|
31
|
+
def destroy_endpoint!
|
32
|
+
Decidim.traceability.perform_action!(
|
33
|
+
:delete,
|
34
|
+
endpoint,
|
35
|
+
current_user
|
36
|
+
) do
|
37
|
+
endpoint.destroy!
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ComparativeStats
|
5
|
+
module Admin
|
6
|
+
# A command with all the business logic when updating an endpoint
|
7
|
+
class UpdateEndpoint < Rectify::Command
|
8
|
+
# Public: Initializes the command.
|
9
|
+
#
|
10
|
+
# form - A form object with the params.
|
11
|
+
def initialize(endpoint, form, user)
|
12
|
+
@endpoint = endpoint
|
13
|
+
@form = form
|
14
|
+
@user = user
|
15
|
+
end
|
16
|
+
|
17
|
+
# Executes the command. Broadcasts these events:
|
18
|
+
#
|
19
|
+
# - :ok when everything is valid.
|
20
|
+
# - :invalid if the form wasn't valid and we couldn't proceed.
|
21
|
+
#
|
22
|
+
# Returns nothing.
|
23
|
+
def call
|
24
|
+
return broadcast(:invalid) if form.invalid?
|
25
|
+
|
26
|
+
update_endpoint!
|
27
|
+
broadcast(:ok)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
attr_reader :form
|
33
|
+
|
34
|
+
def update_endpoint!
|
35
|
+
Decidim.traceability.update!(
|
36
|
+
@endpoint,
|
37
|
+
@user,
|
38
|
+
endpoint: form.endpoint,
|
39
|
+
name: form.name,
|
40
|
+
api_version: form.context.api.name_and_version.version,
|
41
|
+
active: form.active
|
42
|
+
)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|