decidim-comparative_stats 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "decidim/comparative_stats/admin"
|
|
4
|
+
require "decidim/comparative_stats/engine"
|
|
5
|
+
require "decidim/comparative_stats/admin_engine"
|
|
6
|
+
require "chartkick"
|
|
7
|
+
|
|
8
|
+
module Decidim
|
|
9
|
+
# This namespace holds the logic of the `ComparativeStats` component. This component
|
|
10
|
+
# allows users to create comparative_stats in a participatory space.
|
|
11
|
+
module ComparativeStats
|
|
12
|
+
include ActiveSupport::Configurable
|
|
13
|
+
|
|
14
|
+
autoload :ApiFetcher, "decidim/comparative_stats/api_fetcher"
|
|
15
|
+
autoload :CachedHTTPAdapter, "decidim/comparative_stats/cached_http_adapter"
|
|
16
|
+
|
|
17
|
+
# Sets the expiration time for the statistic data.
|
|
18
|
+
config_accessor :stats_cache_expiration_time do
|
|
19
|
+
24.hours
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Decidim
|
|
4
|
+
module ComparativeStats
|
|
5
|
+
# This is the engine that runs on the public interface of `ComparativeStats`.
|
|
6
|
+
class AdminEngine < ::Rails::Engine
|
|
7
|
+
isolate_namespace Decidim::ComparativeStats::Admin
|
|
8
|
+
|
|
9
|
+
paths["db/migrate"] = nil
|
|
10
|
+
paths["lib/tasks"] = nil
|
|
11
|
+
|
|
12
|
+
routes do
|
|
13
|
+
# Add admin engine routes here
|
|
14
|
+
resources :endpoints
|
|
15
|
+
get "graphs/:graph", to: "graphs#show", as: :graphs, defaults: { graph: "global_stats" }
|
|
16
|
+
root to: "endpoints#index"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
initializer "decidim_comparative_stats.admin_mount_routes" do
|
|
20
|
+
Decidim::Core::Engine.routes do
|
|
21
|
+
mount Decidim::ComparativeStats::AdminEngine, at: "/admin/comparative_stats", as: "decidim_admin_comparative_stats"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
initializer "decidim_comparative_stats.add_cells_view_paths" do
|
|
26
|
+
Cell::ViewModel.view_paths << File.expand_path("#{Decidim::ComparativeStats::Engine.root}/app/cells")
|
|
27
|
+
Cell::ViewModel.view_paths << File.expand_path("#{Decidim::ComparativeStats::Engine.root}/app/views") # for partials
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
initializer "decidim_comparative_stats.admin_assets" do |app|
|
|
31
|
+
app.config.assets.precompile += %w(admin/comparative_stats_manifest.js admin/comparative_stats_manifest.css)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def load_seed
|
|
35
|
+
nil
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
initializer "decidim_comparative_stats.admin_menu" do
|
|
39
|
+
Decidim.menu :admin_menu do |menu|
|
|
40
|
+
menu.item I18n.t("menu.comparative_stats", scope: "decidim.admin"),
|
|
41
|
+
decidim_admin_comparative_stats.endpoints_path,
|
|
42
|
+
icon_name: "graph",
|
|
43
|
+
position: 3.5,
|
|
44
|
+
active: is_active_link?(decidim_admin_comparative_stats.endpoints_path, :inclusive) ||
|
|
45
|
+
is_active_link?(decidim_admin_comparative_stats.graphs_path, :inclusive)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "graphlient"
|
|
4
|
+
require "decidim/comparative_stats/version"
|
|
5
|
+
|
|
6
|
+
module Decidim
|
|
7
|
+
module ComparativeStats
|
|
8
|
+
# Class used to fetch and validate Decidim API calls
|
|
9
|
+
class ApiFetcher
|
|
10
|
+
def initialize(endpoint)
|
|
11
|
+
@errors = []
|
|
12
|
+
@queries = {}
|
|
13
|
+
@endpoint = endpoint
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
attr_reader :errors, :endpoint
|
|
17
|
+
|
|
18
|
+
attr_writer :client
|
|
19
|
+
|
|
20
|
+
def client
|
|
21
|
+
@client ||= Graphlient::Client.new(endpoint,
|
|
22
|
+
http: CachedHTTPAdapter,
|
|
23
|
+
http_options: {
|
|
24
|
+
read_timeout: 20,
|
|
25
|
+
write_timeout: 30
|
|
26
|
+
})
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# When creating name and version are fetched from the api
|
|
30
|
+
# Update action should allow the user to change the name but not the version
|
|
31
|
+
def name_and_version
|
|
32
|
+
@name_and_version ||= fetch_name_and_version.data.decidim
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Queries the GraphQL api using one of files in lib/decidim/comparative_stats/queries
|
|
36
|
+
def query(tag)
|
|
37
|
+
@queries[tag] ||= client.query versioned_query(tag)
|
|
38
|
+
rescue Faraday::Error
|
|
39
|
+
@errors << "Not a valid Decidim API URL"
|
|
40
|
+
rescue Graphlient::Errors::Error => e
|
|
41
|
+
@errors << e.message
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Checks if is a valid Decidim API URL
|
|
45
|
+
def valid?(min_version = MIN_API_VERSION)
|
|
46
|
+
response = fetch_name_and_version
|
|
47
|
+
return false unless response
|
|
48
|
+
|
|
49
|
+
if Gem::Version.new(min_version) > Gem::Version.new(response.data.decidim.version)
|
|
50
|
+
@errors << "Decidim version detect (#{response.data.decidim.version}) should be at least #{min_version}"
|
|
51
|
+
return false
|
|
52
|
+
end
|
|
53
|
+
true
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# returns the last error
|
|
57
|
+
def error
|
|
58
|
+
@errors.last
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
def versioned_query(tag)
|
|
64
|
+
file = File.join(__dir__, "queries", "#{tag}.graphql")
|
|
65
|
+
raise NameError unless File.exist?(file)
|
|
66
|
+
|
|
67
|
+
unless tag == "name_and_version"
|
|
68
|
+
if Gem::Version.new(name_and_version.version) < Gem::Version.new("0.23")
|
|
69
|
+
alt_file = File.join(__dir__, "queries", "v022", "#{tag}.graphql")
|
|
70
|
+
file = alt_file if File.exist?(alt_file)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
File.open(file).read
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Syntactic sugar to query graphql queries:
|
|
77
|
+
# i.e:
|
|
78
|
+
# query "name_and_version" => fetch_name_and_version
|
|
79
|
+
def method_missing(name)
|
|
80
|
+
_, key = name.to_s.split("fetch_")
|
|
81
|
+
if key
|
|
82
|
+
query key
|
|
83
|
+
else
|
|
84
|
+
super
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def respond_to_missing?(method_name, include_private = false)
|
|
89
|
+
method_name.to_s.start_with?("fetch_") || super
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "graphlient/adapters/http/http_adapter"
|
|
4
|
+
|
|
5
|
+
module Decidim
|
|
6
|
+
module ComparativeStats
|
|
7
|
+
class CachedHTTPAdapter < Graphlient::Adapters::HTTP::FaradayAdapter
|
|
8
|
+
def execute(document:, operation_name: nil, variables: {}, context: {})
|
|
9
|
+
body = {}
|
|
10
|
+
# Strip uniq identifier generated by GraphQL class
|
|
11
|
+
body["query"] = document.to_query_string.gsub(/GraphQL__Client__OperationDefinition_[0-9 ]+/, "")
|
|
12
|
+
body["variables"] = variables if variables.any?
|
|
13
|
+
|
|
14
|
+
Rails.cache.fetch(
|
|
15
|
+
"graphlient/api_queries/#{url.hash}/#{body.to_json.hash}",
|
|
16
|
+
expires_in: Decidim::ComparativeStats.stats_cache_expiration_time
|
|
17
|
+
) do
|
|
18
|
+
super
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails"
|
|
4
|
+
require "decidim/core"
|
|
5
|
+
|
|
6
|
+
module Decidim
|
|
7
|
+
module ComparativeStats
|
|
8
|
+
# This is the engine that runs on the public interface of comparative_stats.
|
|
9
|
+
class Engine < ::Rails::Engine
|
|
10
|
+
isolate_namespace Decidim::ComparativeStats
|
|
11
|
+
|
|
12
|
+
routes do
|
|
13
|
+
# Add engine routes here
|
|
14
|
+
get "widgets/:graph", to: "widgets#show", as: :widget, defaults: { graph: "global_stats" }
|
|
15
|
+
root to: "widgets#show"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
initializer "decidim_comparative_stats.mount_routes" do
|
|
19
|
+
Decidim::Core::Engine.routes do
|
|
20
|
+
mount Decidim::ComparativeStats::Engine, at: "/comparative_stats", as: "decidim_comparative_stats"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
initializer "decidim_comparative_stats.add_cells_view_paths" do
|
|
25
|
+
Cell::ViewModel.view_paths << File.expand_path("#{Decidim::ComparativeStats::Engine.root}/app/cells")
|
|
26
|
+
Cell::ViewModel.view_paths << File.expand_path("#{Decidim::ComparativeStats::Engine.root}/app/views") # for partials
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
initializer "decidim_comparative_stats.assets" do |app|
|
|
30
|
+
app.config.assets.precompile += %w(comparative_stats_manifest.js comparative_stats_manifest.css)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
query {
|
|
2
|
+
assemblies {
|
|
3
|
+
id
|
|
4
|
+
slug
|
|
5
|
+
components (filter: {withGeolocationEnabled: true }) {
|
|
6
|
+
id
|
|
7
|
+
__typename
|
|
8
|
+
...geolocatedMeetings
|
|
9
|
+
...geolocatedProposals
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
participatoryProcesses {
|
|
13
|
+
id
|
|
14
|
+
slug
|
|
15
|
+
components (filter: {withGeolocationEnabled: true }) {
|
|
16
|
+
id
|
|
17
|
+
__typename
|
|
18
|
+
...geolocatedMeetings
|
|
19
|
+
...geolocatedProposals
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
fragment geolocatedMeetings on Meetings {
|
|
25
|
+
meetings {
|
|
26
|
+
edges {
|
|
27
|
+
node {
|
|
28
|
+
id
|
|
29
|
+
address
|
|
30
|
+
title {
|
|
31
|
+
translations {
|
|
32
|
+
text
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
description {
|
|
36
|
+
translations {
|
|
37
|
+
text
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
startTime
|
|
41
|
+
endTime
|
|
42
|
+
location {
|
|
43
|
+
translations {
|
|
44
|
+
text
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
locationHints {
|
|
48
|
+
translations {
|
|
49
|
+
text
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
coordinates {
|
|
53
|
+
latitude
|
|
54
|
+
longitude
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
fragment geolocatedProposals on Proposals {
|
|
62
|
+
proposals {
|
|
63
|
+
edges {
|
|
64
|
+
node {
|
|
65
|
+
id
|
|
66
|
+
address
|
|
67
|
+
title {
|
|
68
|
+
translations {
|
|
69
|
+
text
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
body {
|
|
73
|
+
translations {
|
|
74
|
+
text
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
coordinates {
|
|
78
|
+
latitude
|
|
79
|
+
longitude
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
query {
|
|
2
|
+
assemblies {
|
|
3
|
+
id
|
|
4
|
+
slug
|
|
5
|
+
components (filter: {withGeolocationEnabled: true }) {
|
|
6
|
+
id
|
|
7
|
+
__typename
|
|
8
|
+
...geolocatedMeetings
|
|
9
|
+
...geolocatedProposals
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
participatoryProcesses {
|
|
13
|
+
id
|
|
14
|
+
slug
|
|
15
|
+
components (filter: {withGeolocationEnabled: true }) {
|
|
16
|
+
id
|
|
17
|
+
__typename
|
|
18
|
+
...geolocatedMeetings
|
|
19
|
+
...geolocatedProposals
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
fragment geolocatedMeetings on Meetings {
|
|
25
|
+
meetings {
|
|
26
|
+
edges {
|
|
27
|
+
node {
|
|
28
|
+
id
|
|
29
|
+
address
|
|
30
|
+
title {
|
|
31
|
+
translations {
|
|
32
|
+
text
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
description {
|
|
36
|
+
translations {
|
|
37
|
+
text
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
startTime
|
|
41
|
+
endTime
|
|
42
|
+
location {
|
|
43
|
+
translations {
|
|
44
|
+
text
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
locationHints {
|
|
48
|
+
translations {
|
|
49
|
+
text
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
coordinates {
|
|
53
|
+
latitude
|
|
54
|
+
longitude
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
fragment geolocatedProposals on Proposals {
|
|
62
|
+
proposals {
|
|
63
|
+
edges {
|
|
64
|
+
node {
|
|
65
|
+
id
|
|
66
|
+
address
|
|
67
|
+
title
|
|
68
|
+
body
|
|
69
|
+
coordinates {
|
|
70
|
+
latitude
|
|
71
|
+
longitude
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "decidim/core/test/factories"
|
|
4
|
+
|
|
5
|
+
FactoryBot.define do
|
|
6
|
+
factory :endpoint, class: "Decidim::ComparativeStats::Endpoint" do
|
|
7
|
+
endpoint { Faker::Internet.url }
|
|
8
|
+
name { Faker::Name.name }
|
|
9
|
+
api_version { Decidim::ComparativeStats::MIN_API_VERSION }
|
|
10
|
+
organization { create :organization }
|
|
11
|
+
active { true }
|
|
12
|
+
end
|
|
13
|
+
end
|