decidim 0.29.1 → 0.30.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/decidim.gemspec +2 -2
- data/docs/antora.yml +1 -1
- data/docs/modules/configure/assets/images/system-dashboard.png +0 -0
- data/docs/modules/configure/assets/images/system-log_in.png +0 -0
- data/docs/modules/configure/pages/environment_variables.adoc +24 -0
- data/docs/modules/configure/pages/initializer.adoc +26 -0
- data/docs/modules/configure/pages/system.adoc +145 -0
- data/docs/modules/customize/pages/menu.adoc +1 -1
- data/docs/modules/develop/assets/images/taxonomies.png +0 -0
- data/docs/modules/develop/pages/ai_tools/lang_detection_formatter.adoc +9 -0
- data/docs/modules/develop/pages/ai_tools/spam_detection_analyzer.adoc +20 -0
- data/docs/modules/develop/pages/ai_tools/spam_detection_service.adoc +25 -0
- data/docs/modules/develop/pages/ai_tools/spam_detection_strategy.adoc +43 -0
- data/docs/modules/develop/pages/ai_tools/spam_detection_trainer.adoc +83 -0
- data/docs/modules/develop/pages/ai_tools.adoc +12 -0
- data/docs/modules/develop/pages/classes/jobs.adoc +1 -1
- data/docs/modules/develop/pages/classes/models.adoc +4 -3
- data/docs/modules/develop/pages/commentable.adoc +127 -0
- data/docs/modules/develop/pages/endorsable.adoc +6 -15
- data/docs/modules/develop/pages/share_tokens.adoc +153 -11
- data/docs/modules/develop/pages/taxonomies.adoc +476 -0
- data/docs/modules/install/pages/manual.adoc +1 -1
- data/docs/modules/install/partials/version_matrix.adoc +4 -2
- data/docs/modules/services/pages/aitools.adoc +164 -0
- data/docs/modules/services/pages/index.adoc +1 -0
- data/docs/modules/services/pages/maps.adoc +2 -2
- data/lib/decidim/version.rb +1 -1
- data/package-lock.json +308 -175
- data/packages/browserslist-config/package.json +2 -2
- data/packages/core/package.json +6 -4
- data/packages/dev/package.json +2 -2
- data/packages/eslint-config/package.json +2 -2
- data/packages/prettier-config/package.json +2 -2
- data/packages/stylelint-config/package.json +2 -2
- data/packages/webpacker/package.json +2 -2
- data/packages/webpacker/src/override-config.js +11 -1
- metadata +56 -43
@@ -1,6 +1,6 @@
|
|
1
1
|
= Share tokens
|
2
2
|
|
3
|
-
Share tokens can be assigned to any model to provide a system to share unpublished resources with
|
3
|
+
Share tokens can be assigned to any model to provide a system to share unpublished resources with expiration dates through the creation/destruction of tokens.
|
4
4
|
|
5
5
|
A share token is created by a user with an expiration time, and can be added as a query param to access otherwise restricted locations.
|
6
6
|
|
@@ -12,7 +12,7 @@ The model must `include Decidim::ShareableWithToken` and implement `shareable_ur
|
|
12
12
|
----
|
13
13
|
# Public: Public URL for your_resource with given share token as query parameter
|
14
14
|
def shareable_url(share_token)
|
15
|
-
|
15
|
+
your_resource_public_url(self, share_token: share_token.token)
|
16
16
|
end
|
17
17
|
----
|
18
18
|
|
@@ -31,27 +31,169 @@ return unless token.present?
|
|
31
31
|
allow! if Decidim::ShareToken.use!(token_for: your_resource, token: token)
|
32
32
|
----
|
33
33
|
|
34
|
+
Note that, if you are using a controller who is inheriting from `Decidim::ApplicationController`, you do not need to include the `:share_token` in the context when calling methods like `enforce_permission_to`, as it is already included in the `Decidim::NeedsPermissions` class through the method `store_share_token`.
|
35
|
+
|
34
36
|
== Manage tokens
|
35
37
|
|
36
|
-
|
38
|
+
By default, participatory spaces like process, assemblies, conferences and initiatives are configured to have share tokens, as well as the individual components that are included in them. Participatory spaces have a "Share tokens" tab in the admin view, where you can create new tokens, see the list of existing ones, and revoke them.
|
39
|
+
Tokens can also be managed in the components view similarly as other resources to give pre-access (with and action icon like permissions for instance).
|
40
|
+
|
41
|
+
Tokens generated for a participatory space are valid for all the components included in it (regardless of their publication status), and tokens generated for a component are valid for that component only.
|
42
|
+
|
43
|
+
== Implementation for participatory spaces
|
44
|
+
|
45
|
+
In order to implement share tokens for a participatory spaces, you need to:
|
46
|
+
|
47
|
+
=== 1. Routes
|
48
|
+
|
49
|
+
Add the `share_tokens` CRUD routes in your `admin_engine.rb` file:
|
50
|
+
|
51
|
+
[source,ruby]
|
52
|
+
----
|
53
|
+
scope "/assemblies/:assembly_slug" do
|
54
|
+
...
|
55
|
+
resources :assembly_share_tokens, except: [:show], path: "share_tokens"
|
56
|
+
...
|
57
|
+
end
|
58
|
+
----
|
59
|
+
|
60
|
+
=== 2. Controller
|
61
|
+
|
62
|
+
Add the controller for the participatory space, it only requires to inherit from `Decidim::Admin::ShareTokensController` and define the `resource` method to return the participatory space:
|
63
|
+
|
64
|
+
[source,ruby]
|
65
|
+
----
|
66
|
+
# frozen_string_literal: true
|
67
|
+
|
68
|
+
module Decidim
|
69
|
+
module Assemblies
|
70
|
+
module Admin
|
71
|
+
# This controller allows sharing unpublished things.
|
72
|
+
# It is targeted for customizations for sharing unpublished things that lives under
|
73
|
+
# an assembly.
|
74
|
+
class AssemblyShareTokensController < Decidim::Admin::ShareTokensController
|
75
|
+
include Concerns::AssemblyAdmin
|
76
|
+
|
77
|
+
def resource
|
78
|
+
current_assembly
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
----
|
85
|
+
|
86
|
+
=== 3. Menu entry
|
87
|
+
|
88
|
+
Add the menu entry for the share tokens in the participatory space admin view. In Decidim we do this in the `menu.rb` file for each participatory space:
|
89
|
+
|
90
|
+
[source,ruby]
|
91
|
+
----
|
92
|
+
Decidim.menu :admin_assembly_menu do |menu|
|
93
|
+
...
|
94
|
+
menu.add_item :assembly_share_tokens,
|
95
|
+
I18n.t("menu.share_tokens", scope: "decidim.admin"),
|
96
|
+
decidim_admin_assemblies.assembly_share_tokens_path(current_participatory_space),
|
97
|
+
active: is_active_link?(decidim_admin_assemblies.assembly_share_tokens_path(current_participatory_space)),
|
98
|
+
icon_name: "share-line",
|
99
|
+
if: allowed_to?(:read, :share_tokens, current_participatory_space:)
|
100
|
+
...
|
101
|
+
end
|
102
|
+
----
|
103
|
+
|
104
|
+
=== 4. Model
|
105
|
+
|
106
|
+
Ensure your participatory space model includes the `Decidim::ShareableWithToken` module and implements the `shareable_url` method:
|
107
|
+
|
108
|
+
[source,ruby]
|
109
|
+
----
|
110
|
+
module Decidim
|
111
|
+
class Assembly < ApplicationRecord
|
112
|
+
...
|
113
|
+
include Decidim::ShareableWithToken
|
114
|
+
...
|
115
|
+
def shareable_url(share_token)
|
116
|
+
EngineRouter.main_proxy(self).assembly_url(self, share_token: share_token.token)
|
117
|
+
end
|
118
|
+
...
|
119
|
+
end
|
120
|
+
end
|
121
|
+
----
|
122
|
+
|
123
|
+
=== 5. Permissions
|
124
|
+
|
125
|
+
Add the permissions logic to the participatory space controller in the `permissions.rb` file:
|
126
|
+
|
127
|
+
For admin controllers:
|
37
128
|
|
38
129
|
[source,ruby]
|
39
130
|
----
|
40
|
-
|
131
|
+
allow! if permission_action.subject == :share_tokens
|
132
|
+
----
|
133
|
+
|
134
|
+
For frontend controllers:
|
135
|
+
|
136
|
+
[source,ruby]
|
137
|
+
----
|
138
|
+
token = context[:share_token]
|
139
|
+
|
140
|
+
return unless token.present?
|
141
|
+
|
142
|
+
allow! if Decidim::ShareToken.use!(token_for: current_assembly, token: token)
|
41
143
|
----
|
42
144
|
|
43
|
-
|
145
|
+
== Implementation for components
|
44
146
|
|
45
|
-
|
147
|
+
Components all inherit from `Decidim::Component`, so they already have the `Decidim::ShareableWithToken` module included. But you still need to do some steps:
|
46
148
|
|
47
|
-
|
149
|
+
=== 1. Routes
|
150
|
+
|
151
|
+
Add the `share_tokens` CRUD routes in your `admin_engine.rb` file:
|
48
152
|
|
49
153
|
[source,ruby]
|
50
154
|
----
|
51
|
-
|
52
|
-
|
53
|
-
|
155
|
+
scope "/assemblies/:assembly_slug" do
|
156
|
+
...
|
157
|
+
resources :components do
|
158
|
+
...
|
159
|
+
resources :component_share_tokens, except: [:show], path: "share_tokens", as: "share_tokens"
|
160
|
+
...
|
161
|
+
end
|
162
|
+
end
|
163
|
+
----
|
164
|
+
|
165
|
+
=== 2. Controller
|
166
|
+
|
167
|
+
Add the controller for the component, it only requires to inherit from `Decidim::Admin::ShareTokensController` and define the `resource` method to return the component:
|
54
168
|
|
55
|
-
|
169
|
+
[source,ruby]
|
170
|
+
----
|
171
|
+
# frozen_string_literal: true
|
172
|
+
|
173
|
+
module Decidim
|
174
|
+
module Assemblies
|
175
|
+
module Admin
|
176
|
+
# This controller allows sharing unpublished things.
|
177
|
+
# It is targeted for customizations for sharing unpublished things that lives under
|
178
|
+
# an assembly.
|
179
|
+
class ComponentShareTokensController < Decidim::Admin::ShareTokensController
|
180
|
+
include Concerns::AssemblyAdmin
|
181
|
+
|
182
|
+
def resource
|
183
|
+
@resource ||= current_participatory_space.components.find(params[:component_id])
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
56
188
|
end
|
57
189
|
----
|
190
|
+
|
191
|
+
=== 3. Permissions
|
192
|
+
|
193
|
+
Similarly, add the same permissions logic to the component controller in the `permissions.rb` file as for participatory spaces.
|
194
|
+
|
195
|
+
|
196
|
+
== Other implementations
|
197
|
+
|
198
|
+
You can implement share tokens for any other model by following the same steps as for participatory spaces and components.
|
199
|
+
In that case, however, you might have to override some methods from the `Decidim::Admin::ShareTokensController` to adapt them to your model (check the source code for details).
|
@@ -0,0 +1,476 @@
|
|
1
|
+
= Taxonomies in Decidim
|
2
|
+
|
3
|
+
The concept of being "taxonomizable" in Decidim refers to the ability of various entities (such as proposals, participatory processes, assemblies, etc.) to be categorized and organized using taxonomies. This allows for better organization, filtering, and searching of these entities within the platform.
|
4
|
+
|
5
|
+
Taxonomies replaces the old concepts of "Participatory process types", "Assemblies types", "Scopes", "Areas" and "Categories" in Decidim. They are a more flexible although require admins to define the taxonomies and assign them to the entities.
|
6
|
+
|
7
|
+
== Architecture of the taxonomies
|
8
|
+
|
9
|
+
Taxonomies in Decidim are organized in a tree structure (with a maximum of three levels).
|
10
|
+
|
11
|
+
In order to assign a taxonomy to a resource, first some filters must be defined in the admin for each participatory space. These filters are associated with a root taxonomy and will have a list of child filter items, each of them associated with a child taxonomy. These items will indicate which taxonomies are available to filter the entities in that particular participatory space or component. Note that this filters does not prevent any resource to be assigned to any taxonomy, they are just used to filter which taxonomies are available to admins or users to assign or search.
|
12
|
+
|
13
|
+
image::taxonomies.png[Architecture of the taxonomies]
|
14
|
+
|
15
|
+
1. **Taxonomies table**: Can have a parent or not. Taxonomies without a parent are "root taxonomies", they cannot be linked to any resource directly.
|
16
|
+
|
17
|
+
2. **Taxonomy filters**: Filters are defined for each participatory space type (meaning they are valid for all of spaces of the same type). They are linked to a root category, with no limit of filters allowed to be linked to a single root taxonomy. Each filter, has many "filter items".
|
18
|
+
|
19
|
+
3. **Taxonomy filter item**: This is used to allow filtering the final taxonomies that are shown in the web frontend. This way, certain component can show some parts of taxonomies and another other, while all of them are linked to the same taxonomy tables.
|
20
|
+
|
21
|
+
== Types of taxonomies
|
22
|
+
|
23
|
+
There are two types of taxonomies in Decidim:
|
24
|
+
|
25
|
+
- **Root taxonomies**: These are the "parent" taxonomies that can have child taxonomies. They are used to group and organize child taxonomies. Resource cannot be directly assigned to root taxonomies but to their child taxonomies.
|
26
|
+
|
27
|
+
- **Child taxonomies**: These are the "child" taxonomies that can be assigned to resources. They can be assigned to root taxonomies or other child taxonomies.
|
28
|
+
|
29
|
+
== The `Taxonomizable` Concern in Decidim
|
30
|
+
|
31
|
+
The `Taxonomizable` concern in Decidim is a module that provides functionality to categorize and organize different entities using taxonomies. This concern can be included in models to make them taxonomizable.
|
32
|
+
|
33
|
+
=== Example Usage
|
34
|
+
|
35
|
+
Here is an example of how the `Taxonomizable` concern might be used in a model:
|
36
|
+
|
37
|
+
[source,ruby]
|
38
|
+
....
|
39
|
+
# frozen_string_literal: true
|
40
|
+
|
41
|
+
module Decidim
|
42
|
+
class ParticipatoryProcess < ApplicationRecord
|
43
|
+
include Decidim::Taxonomizable
|
44
|
+
|
45
|
+
# Other model code...
|
46
|
+
end
|
47
|
+
end
|
48
|
+
....
|
49
|
+
|
50
|
+
In this example, the `ParticipatoryProcess` model includes the `Decidim::Taxonomizable` concern, which allows it to be categorized using taxonomies that can be found as associations like:
|
51
|
+
|
52
|
+
[source,ruby]
|
53
|
+
....
|
54
|
+
participatory_process.taxonomies
|
55
|
+
....
|
56
|
+
|
57
|
+
== Taxonomy filters
|
58
|
+
|
59
|
+
Taxonomies can be used to filter entities in the frontend. The `Decidim::TaxonomyFilter` class is used to define the filters in each participatory space that will apply in the frontend.
|
60
|
+
|
61
|
+
Each filter is associated with a root taxonomy and it will have a list of child filter items, each of them associated with a child taxonomy. These items will indicate which taxonomies are available to filter the entities in that particular participatory space or component.
|
62
|
+
|
63
|
+
|
64
|
+
== ActiveRecord implementation
|
65
|
+
|
66
|
+
**Root taxonomies** and taxonomy items are in the same table. A "root taxonomy" is simply the first level (no parents). A resource can be associated to a taxonomy through the "taxonomizations" table. Validations are in place to prevent associate a resource to a root taxonomy. Currently, there are no validations to prevent destroy a taxonomy if it has taxonomizations (this might change in the future, but this is by design at this point).
|
67
|
+
|
68
|
+
[source,ruby]
|
69
|
+
....
|
70
|
+
module Decidim
|
71
|
+
class Taxonomy < ApplicationRecord
|
72
|
+
before_validation :update_part_of, on: :update
|
73
|
+
after_create_commit :create_part_of
|
74
|
+
belongs_to :organization, inverse_of: :taxonomies
|
75
|
+
belongs_to :parent, inverse_of: :children, optional: true
|
76
|
+
has_many :children, inverse_of: :parent, dependent: :destroy
|
77
|
+
has_many :taxonomizations, dependent: :destroy
|
78
|
+
has_many :taxonomy_filters, dependent: :destroy
|
79
|
+
has_many :taxonomy_filter_items, dependent: :destroy
|
80
|
+
|
81
|
+
validates :name, presence: true
|
82
|
+
validate :validate_max_children_levels
|
83
|
+
validate :forbid_cycles
|
84
|
+
...
|
85
|
+
....
|
86
|
+
|
87
|
+
**Taxonomy filters** are associated to a root taxonomy and have many taxonomy_filter_items, which in turn are associated to a specific taxonomy. The final tree of taxonomies is built in the frontend using the specified items only.
|
88
|
+
|
89
|
+
[source,ruby]
|
90
|
+
....
|
91
|
+
module Decidim
|
92
|
+
class TaxonomyFilter < ApplicationRecord
|
93
|
+
belongs_to :root_taxonomy, inverse_of: :taxonomy_filters
|
94
|
+
has_many :filter_items, inverse_of: :taxonomy_filter, dependent: :destroy
|
95
|
+
|
96
|
+
validate :root_taxonomy_is_root
|
97
|
+
validate :space_manifest_is_registered
|
98
|
+
|
99
|
+
delegate :name, to: :root_taxonomy
|
100
|
+
...
|
101
|
+
....
|
102
|
+
|
103
|
+
[source,ruby]
|
104
|
+
....
|
105
|
+
module Decidim
|
106
|
+
class TaxonomyFilterItem < ApplicationRecord
|
107
|
+
belongs_to :taxonomy_filter, inverse_of: :filter_items
|
108
|
+
belongs_to :taxonomy_item, inverse_of: :taxonomy_filter_items
|
109
|
+
|
110
|
+
validate :taxonomy_item_is_not_root
|
111
|
+
validate :taxonomy_item_is_child_of_taxonomy_filter_root
|
112
|
+
...
|
113
|
+
....
|
114
|
+
|
115
|
+
Note that filters use the same name as the parent taxonomy by default, but it is possible either to assign a public (presented in the frontend for final users) and an internal name (for admins reference) to the filter.
|
116
|
+
|
117
|
+
== Reusable parts
|
118
|
+
|
119
|
+
=== The taxonomy_filters Settings type
|
120
|
+
|
121
|
+
See `decidim-admin/app/helpers/decidim/admin/settings_helper.rb` and `decidim-core/lib/decidim/settings_manifest.rb`.
|
122
|
+
|
123
|
+
It is a new type of form field for components to allow specify the ids of the taxonomy filters that going to be used in that component. Uses a lateral drawer modal to choose from the available ones. To use it, it is enough to add the attribute `taxonomy_filters` in the components definition:
|
124
|
+
|
125
|
+
[source,ruby]
|
126
|
+
....
|
127
|
+
# decidim-debates/lib/decidim/debates/component.rb
|
128
|
+
Decidim.register_component(:debates) do |component|
|
129
|
+
component.engine = Decidim::Debates::Engine
|
130
|
+
...
|
131
|
+
component.settings(:global) do |settings|
|
132
|
+
settings.attribute :taxonomy_filters, type: :taxonomy_filters
|
133
|
+
...
|
134
|
+
....
|
135
|
+
|
136
|
+
=== The concern HasTaxonomySettings
|
137
|
+
|
138
|
+
See `decidim-core/lib/decidim/has_taxonomy_settings.rb`.
|
139
|
+
|
140
|
+
Provides methods to extract available taxonomies and filters according to the components settings' configuration. These are intended to be used in places where the user has to assign taxonomies to a resource. It is included in the `Component` model.
|
141
|
+
|
142
|
+
=== The concern HasTaxonomyFormAttributes
|
143
|
+
|
144
|
+
See `decidim-admin/app/forms/concerns/decidim/has_taxonomy_form_attributes.rb`
|
145
|
+
|
146
|
+
Provides with attribute definitions for adding multiple taxonomies in a `Decidim::Form` object. It only requires for the implementing class to return the manifest of the participatory space (which is used to obtain the list of filters available). Used in every resource form that needs to include taxonomies (ie: `AssemblyForm`, `ProposalForm`, etc...).
|
147
|
+
|
148
|
+
A related file is `decidim-core/app/helpers/decidim/taxonomies_helper.rb` which defines the method `taxonomy_items_options_for_filter` that is used in the form views as:
|
149
|
+
|
150
|
+
[source,erb]
|
151
|
+
----
|
152
|
+
<% if @form.taxonomy_filters&.any? %>
|
153
|
+
<% @form.taxonomy_filters.each do |filter| %>
|
154
|
+
<div class="row column">
|
155
|
+
<%= filter_taxonomy_items_select_field form, :taxonomies, filter %>
|
156
|
+
</div>
|
157
|
+
<% end %>
|
158
|
+
<% end %>
|
159
|
+
----
|
160
|
+
|
161
|
+
=== The concern Filterable
|
162
|
+
|
163
|
+
See `decidim-admin/app/controllers/concerns/decidim/admin/filterable.rb`
|
164
|
+
|
165
|
+
Provides methods to obtain taxonomies and defines ransack attributes for searching resources using taxonomies. Added in every controller that need to search by taxonomy (public or admin side).
|
166
|
+
For instance, to show the taxonomies in the sidebar of the public frontend usually you just need it to add to the filter_sections method like we do in the FilterAssembliesHelper (`decidim-assemblies/app/helpers/decidim/assemblies/filter_assemblies_helper.rb`):
|
167
|
+
|
168
|
+
[source,ruby]
|
169
|
+
....
|
170
|
+
def filter_sections
|
171
|
+
items = [
|
172
|
+
{ method: :with_any_type, collection: filter_types_values, label: t("decidim.assemblies.assemblies.filters.type"), id: "type" }
|
173
|
+
]
|
174
|
+
|
175
|
+
available_taxonomy_filters.find_each do |taxonomy_filter|
|
176
|
+
items.append(method: "with_any_taxonomies[#{taxonomy_filter.root_taxonomy_id}]",
|
177
|
+
collection: filter_taxonomy_values_for(taxonomy_filter),
|
178
|
+
label: decidim_sanitize_translated(taxonomy_filter.name),
|
179
|
+
id: "taxonomy")
|
180
|
+
end
|
181
|
+
|
182
|
+
items.reject { |item| item[:collection].blank? }
|
183
|
+
end
|
184
|
+
|
185
|
+
# in case of a resource this is just `current_component.available_taxonomy_filters` provided by `HasTaxonomySettings`
|
186
|
+
def available_taxonomy_filters
|
187
|
+
Decidim::TaxonomyFilter.for(:assemblies)
|
188
|
+
end
|
189
|
+
....
|
190
|
+
|
191
|
+
== Importing taxonomies from old models (categories, scopes, etc)
|
192
|
+
|
193
|
+
In order to import the old taxonomies to the new system, a rake task is provided. This rake task will create the new taxonomies and assign the old resources to them. It also creates the filters and its associated filter items in each type of participatory space to match as close as possible the old system.
|
194
|
+
|
195
|
+
The importing script works in two stages:
|
196
|
+
|
197
|
+
=== Create the plan of the import
|
198
|
+
|
199
|
+
This step will create a JSON file with the plan of the import. This file will contain the old taxonomies (for reference only) and the new taxonomies that will be created along with all the associated resources for each of them. It will also contain the filters and filter items that will be created for each type of participatory space.
|
200
|
+
|
201
|
+
This file is created in the `tmp` directory of the running Decidim instance. One file per organization is created inside a subfolder called "taxonomies".
|
202
|
+
|
203
|
+
Example. If you have an organization with a host called "example.com", the file will be created in `tmp/taxonomies/example.com_plan.json`.
|
204
|
+
|
205
|
+
To create the plan, run the following command:
|
206
|
+
|
207
|
+
[source,bash]
|
208
|
+
----
|
209
|
+
bin/rails decidim:taxonomies:make_plan
|
210
|
+
----
|
211
|
+
|
212
|
+
This command will output the path of the file(s) created. Then you can inspect the file to see if everything is correct or even modify it if needed (see the last section of this document for a description of the file format).
|
213
|
+
|
214
|
+
=== Execute the import
|
215
|
+
|
216
|
+
This step will execute the plan created in the previous step. It will create the new taxonomies and assign the resources to them. It will also create the filters and filter items for each type of participatory space.
|
217
|
+
|
218
|
+
You can run the import for a specific organization by passing plan file as an argument. For instance, to import the taxonomies for the organization with the host "example.com", run the following command:
|
219
|
+
|
220
|
+
[source,bash]
|
221
|
+
----
|
222
|
+
bin/rails decidim:taxonomies:import_plan[tmp/taxonomies/example.com_plan.json]
|
223
|
+
----
|
224
|
+
|
225
|
+
If you want to import the taxonomies for all organizations at once, you can run the following command:
|
226
|
+
|
227
|
+
[source,bash]
|
228
|
+
----
|
229
|
+
bin/rails decidim:taxonomies:import_all_plans
|
230
|
+
----
|
231
|
+
|
232
|
+
This command will look for all the plan files in the `tmp/taxonomies` directory
|
233
|
+
|
234
|
+
==== Updating metrics
|
235
|
+
|
236
|
+
Internal metrics can be assigned to a category. However as this table can be very large, it is not included in the import process.
|
237
|
+
To update the metrics, you can use the `decidim:taxonomies:update_metrics[tmp/taxonomies/example.com_result.json]` rake task. This task will convert the old categorization metrics to the new taxonomy metrics.
|
238
|
+
|
239
|
+
You can also update all the metrics for all organizations at once by running the following command:
|
240
|
+
|
241
|
+
[source,bash]
|
242
|
+
----
|
243
|
+
bin/rails decidim:taxonomies:update_all_metrics
|
244
|
+
----
|
245
|
+
|
246
|
+
This command will look for all the result files in the `tmp/taxonomies` directory.
|
247
|
+
|
248
|
+
[NOTE]
|
249
|
+
----
|
250
|
+
**IMPORTANT NOTES**
|
251
|
+
|
252
|
+
1. The import script will create each root taxonomy prefixed with the symbol `~`. Just to make sure that the new taxonomies are merged with any existing ones.
|
253
|
+
2. The import script is idempotent, meaning that you can run it multiple times without any side effects. If a taxonomy already exists, it will not be created again.
|
254
|
+
3. If you are not happy with the results of the import, rolling back is as simple as removing the root taxonomies created by the import script from the admin interface, everything related will be removed automatically.
|
255
|
+
4. The process of importing the taxonomies is complex and can take a long time depending on the number of resources to be assigned. It is also provided in good faith and without any warranty. It is recommended to test it in a staging environment with a copy of the production database before running it in production.
|
256
|
+
5. You can specify which models to import by setting the `IMPORTS` environment variable. For instance, to import only the participatory process types and assemblies types, you can run the following command: `IMPORTS="ParticipatoryProcessTypes AssembliesTypes" bin/rails decidim:taxonomies:import_all_plans` (valid models are `ParticipatoryProcessTypes`, `AssembliesTypes`, `Categories`, `Scopes`, `Areas`).
|
257
|
+
----
|
258
|
+
|
259
|
+
=== Other utilities
|
260
|
+
|
261
|
+
Another rake task is provided to reset the counters for the tables related to taxonomies. It might be handy if you suspect that some of the counters are not correct (for instance, if you have deleted some taxonomies manually).
|
262
|
+
|
263
|
+
To reset the counters, run the following command:
|
264
|
+
|
265
|
+
[source,bash]
|
266
|
+
----
|
267
|
+
bin/rails decidim:taxonomies:reset_counters
|
268
|
+
----
|
269
|
+
|
270
|
+
=== Imported equivalences
|
271
|
+
|
272
|
+
The following table shows the equivalences between the old taxonomies and the new ones:
|
273
|
+
|
274
|
+
[cols="1,1,1"]
|
275
|
+
|===
|
276
|
+
| Old categorization model | Root taxonomy created | Filters created
|
277
|
+
|
278
|
+
| Categories
|
279
|
+
| **"~ Categories"**
|
280
|
+
For each participatory space with defined categories, a child taxonomy will be created with the name of the participatory space.
|
281
|
+
| A filter for use in components in each participatory space with defined categories. Each filter will be named after the participatory space name and will be associated with the root taxonomy "~ Categories" with the items corresponding to the child taxonomy created for that space.
|
282
|
+
|
283
|
+
| Scopes
|
284
|
+
| **"~ Scopes"**
|
285
|
+
Simply all existing scopes will be recreated as child taxonomies. However, as scopes can have more than three levels, the import script will only create the first three levels. The deeper levels will be replaced in the third level and renamed with all the names of the parents.
|
286
|
+
| A unique filter for use in components or spaces in each type of participatory space will be created. This filter will be associated with the root taxonomy "~ Scopes" and will have all the scopes as items.
|
287
|
+
|
288
|
+
| Areas
|
289
|
+
| **"~ Areas"**
|
290
|
+
Will behave exactly as scopes but for areas. However, it will not be more than three levels deep in this case as areas are not expected to be that deep.
|
291
|
+
| A unique filter for use in components or spaces in each type of participatory space will be created. This filter will be associated with the root taxonomy "~ Areas" and will have all the areas as items.
|
292
|
+
|
293
|
+
| Participatory process types
|
294
|
+
| **"~ Participatory process types"**
|
295
|
+
All the participatory process types will be recreated as child taxonomies. Each participatory process will be assigned to the corresponding taxonomy.
|
296
|
+
| A unique filter for use in participatory processes will be created. This filter will be associated with the root taxonomy "~ Participatory process types" and will have all the participatory process types as items.
|
297
|
+
|
298
|
+
| Assemblies types
|
299
|
+
| **"~ Assemblies types"**
|
300
|
+
Same as participatory process types but for assemblies.
|
301
|
+
| A unique filter for use in assemblies will be created. This filter will be associated with the root taxonomy "~ Assemblies types" and will have all the assemblies types as items.
|
302
|
+
|
303
|
+
|===
|
304
|
+
|
305
|
+
|
306
|
+
=== Plan file format
|
307
|
+
|
308
|
+
The plan file is a JSON file with three main items in its structure:
|
309
|
+
|
310
|
+
[source,json]
|
311
|
+
----
|
312
|
+
{
|
313
|
+
"organization": {
|
314
|
+
...
|
315
|
+
},
|
316
|
+
"existing_taxonomies": {
|
317
|
+
...
|
318
|
+
},
|
319
|
+
"imported_taxonomies": {
|
320
|
+
...
|
321
|
+
}
|
322
|
+
}
|
323
|
+
----
|
324
|
+
|
325
|
+
==== organization
|
326
|
+
|
327
|
+
This item contains the information about the organization for which the plan was created. It contains the following fields:
|
328
|
+
|
329
|
+
- `id`: The ID of the organization.
|
330
|
+
- `name`: The name of the organization.
|
331
|
+
- `host`: The host of the organization.
|
332
|
+
- `locale`: The default locale of the organization.
|
333
|
+
|
334
|
+
[source,json]
|
335
|
+
----
|
336
|
+
"organization": {
|
337
|
+
"id": 1,
|
338
|
+
"name": "Example Organization",
|
339
|
+
"host": "example.com",
|
340
|
+
"locale": "en"
|
341
|
+
}
|
342
|
+
----
|
343
|
+
|
344
|
+
The most important field is the `locale` field, as it will be used to translate the names of the taxonomies and filters and to make comparisons with the existing taxonomies.
|
345
|
+
|
346
|
+
==== existing_taxonomies
|
347
|
+
|
348
|
+
This item contains the information about the existing taxonomies in the system. It is for reference only and will not be used in the import process. It will contain the tree structure of the existing taxonomies in the system formatted as a JSON object using only the locale of the organization.
|
349
|
+
|
350
|
+
[source,json]
|
351
|
+
----
|
352
|
+
"existing_taxonomies": {
|
353
|
+
"Scopes": {
|
354
|
+
"Scope 1": {
|
355
|
+
"Scope 1.1": {},
|
356
|
+
"Scope 1.2": {}
|
357
|
+
},
|
358
|
+
"Scope 2": {}
|
359
|
+
},
|
360
|
+
"Another taxonomization": {
|
361
|
+
"Another item": {}
|
362
|
+
}
|
363
|
+
...
|
364
|
+
}
|
365
|
+
----
|
366
|
+
|
367
|
+
==== imported_taxonomies
|
368
|
+
|
369
|
+
This item contains the information about the new taxonomies that will be created in the system. It will contain the tree structure of the new taxonomies in the system formatted as a JSON object using only the locale of the organization as keys (but all languages in the values if they can be imported from the old models). It also contains the associated resources for each taxonomy, the filters and filter items for each type of participatory space type.
|
370
|
+
|
371
|
+
[source,json]
|
372
|
+
----
|
373
|
+
"imported_taxonomies": {
|
374
|
+
"decidim_participatory_process_types": {
|
375
|
+
...
|
376
|
+
},
|
377
|
+
"decidim_assemblies_types": {
|
378
|
+
...
|
379
|
+
},
|
380
|
+
"decidim_categories": {
|
381
|
+
...
|
382
|
+
},
|
383
|
+
"decidim_scopes": {
|
384
|
+
...
|
385
|
+
},
|
386
|
+
"decidim_areas": {
|
387
|
+
...
|
388
|
+
}
|
389
|
+
}
|
390
|
+
----
|
391
|
+
|
392
|
+
Each section will contain the following structure:
|
393
|
+
|
394
|
+
[source,json]
|
395
|
+
----
|
396
|
+
"section": {
|
397
|
+
"Root taxonomy name": {
|
398
|
+
"taxonomies": {
|
399
|
+
...
|
400
|
+
},
|
401
|
+
"filters": {
|
402
|
+
...
|
403
|
+
}
|
404
|
+
}
|
405
|
+
}
|
406
|
+
----
|
407
|
+
|
408
|
+
===== `taxonomies`
|
409
|
+
|
410
|
+
A JSON object with the tree structure of the taxonomies to be created. The keys are the names of the taxonomies (using the default locale for the organization) and the values are JSON objects with the properties along with the possible children taxonomies. The properties are:
|
411
|
+
|
412
|
+
- `name`: A JSON object with the translations of the name of the taxonomy
|
413
|
+
- `children`: A JSON object with the children taxonomies (repeating the same structure). If empty it must be an empty object.
|
414
|
+
- `resources`: A JSON object with the resources that will be assigned to the taxonomy. The keys are the GIDs of the resources and the values are the descriptions of the resources. The values are not used in the import process but are useful for reference (depending on the resource, it can be the name or the title).
|
415
|
+
|
416
|
+
===== `filters`
|
417
|
+
|
418
|
+
An array of JSON objects with the filters to be created. Each object will contain the following properties:
|
419
|
+
|
420
|
+
- `name`: The name of the filter (using the default locale for the organization). Admins can translated it later.
|
421
|
+
- `internal_name`: The internal name of the filter (optional).
|
422
|
+
- `space_filter`: A boolean indicating if the filter is a space filter or not (space filters can be used in the participatory space settings).
|
423
|
+
- `space_manifest`: The manifest of the participatory space type to which the filter will be associated.
|
424
|
+
- `items`: An array with the names of the taxonomies that will be associated with the filter. As taxonomies can have multiple levels, each name is an array with the names of the taxonomies in the path to the taxonomy. For instance, if the taxonomy is "Scope 1.1" and it is a child of "Scope 1", the name will be `["Scope 1", "Scope 1.1"]`.
|
425
|
+
- `components`: An array of GIDs of the components that will use the filter (see the component setting `taxonomy_filters`).
|
426
|
+
|
427
|
+
For instance, the `decidim_participatory_process_types` section could look like this:
|
428
|
+
|
429
|
+
[source,json]
|
430
|
+
----
|
431
|
+
"decidim_participatory_process_types": {
|
432
|
+
"~ Participatory process types": {
|
433
|
+
"taxonomies": {
|
434
|
+
"omnis": {
|
435
|
+
"name": {
|
436
|
+
"ca": "explicabo",
|
437
|
+
"en": "omnis",
|
438
|
+
"machine_translations": {
|
439
|
+
"es": "quia"
|
440
|
+
}
|
441
|
+
},
|
442
|
+
"children": {},
|
443
|
+
"resources": {
|
444
|
+
"gid://decidim-development-app/Decidim::ParticipatoryProcess/2": "Architecto vitae dolor minima iure."
|
445
|
+
}
|
446
|
+
},
|
447
|
+
"debitis": {
|
448
|
+
"name": {
|
449
|
+
"ca": "qui",
|
450
|
+
"en": "debitis",
|
451
|
+
"machine_translations": {
|
452
|
+
"es": "et"
|
453
|
+
}
|
454
|
+
},
|
455
|
+
"children": {
|
456
|
+
},
|
457
|
+
"resources": {
|
458
|
+
"gid://decidim-development-app/Decidim::ParticipatoryProcess/1": "Process with no scopes"
|
459
|
+
}
|
460
|
+
}
|
461
|
+
},
|
462
|
+
"filters": [
|
463
|
+
{
|
464
|
+
"name": "~ Participatory process types",
|
465
|
+
"space_filter": true,
|
466
|
+
"space_manifest": "participatory_processes",
|
467
|
+
"items": [
|
468
|
+
["omnis"],
|
469
|
+
["debitis"]
|
470
|
+
],
|
471
|
+
"components": []
|
472
|
+
}
|
473
|
+
]
|
474
|
+
}
|
475
|
+
}
|
476
|
+
----
|
@@ -27,7 +27,7 @@ First, we are going to install https://github.com/rbenv/rbenv[rbenv], for managi
|
|
27
27
|
[source,bash]
|
28
28
|
----
|
29
29
|
sudo apt update
|
30
|
-
sudo apt install -y build-essential curl git libssl-dev zlib1g-dev
|
30
|
+
sudo apt install -y build-essential curl git libssl-dev zlib1g-dev
|
31
31
|
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
|
32
32
|
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
|
33
33
|
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
|