decidim 0.23.6 → 0.24.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of decidim might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Rakefile +1 -0
- data/docs/README.adoc +74 -0
- data/docs/antora.yml +7 -0
- data/docs/modules/configure/pages/environment_variables.adoc +69 -0
- data/docs/modules/configure/pages/index.adoc +16 -0
- data/docs/modules/configure/pages/initializer.adoc +376 -0
- data/docs/modules/customize/assets/images/header-snippet.png +0 -0
- data/docs/modules/customize/assets/images/menu.png +0 -0
- data/docs/modules/customize/assets/images/organization-colors.png +0 -0
- data/docs/modules/customize/pages/authorizations.adoc +22 -0
- data/docs/{customization/code.md → modules/customize/pages/code.adoc} +12 -9
- data/docs/{customization/gemfile.md → modules/customize/pages/gemfile.adoc} +5 -4
- data/docs/modules/customize/pages/images.adoc +7 -0
- data/docs/modules/customize/pages/javascript.adoc +59 -0
- data/docs/modules/customize/pages/menu.adoc +25 -0
- data/docs/modules/customize/pages/oauth.adoc +33 -0
- data/docs/modules/customize/pages/styles.adoc +64 -0
- data/docs/modules/customize/pages/texts.adoc +30 -0
- data/docs/modules/customize/pages/users_registration_mode.adoc +17 -0
- data/docs/{customization/views.md → modules/customize/pages/views.adoc} +13 -13
- data/docs/modules/develop/assets/images/barcelona.png +0 -0
- data/docs/modules/develop/assets/images/helsinki.png +0 -0
- data/docs/modules/develop/assets/images/indices.png +0 -0
- data/docs/{advanced/api.md → modules/develop/pages/api.adoc} +2 -2
- data/docs/{advanced/authorship.md → modules/develop/pages/authorable.adoc} +5 -5
- data/docs/modules/develop/pages/c4_component.adoc +91 -0
- data/docs/modules/develop/pages/c4_container.adoc +42 -0
- data/docs/modules/develop/pages/c4_context.adoc +35 -0
- data/docs/{advanced/components.md → modules/develop/pages/components.adoc} +47 -10
- data/docs/{advanced/content_blocks.md → modules/develop/pages/content_blocks.adoc} +16 -13
- data/docs/{advanced/content_processors.md → modules/develop/pages/content_processors.adoc} +25 -19
- data/docs/modules/develop/pages/data-picker.adoc +85 -0
- data/docs/modules/develop/pages/deploy.adoc +15 -0
- data/docs/modules/develop/pages/docker.adoc +12 -0
- data/docs/{advanced/embeddable.md → modules/develop/pages/embeddable.adoc} +6 -6
- data/docs/{advanced/endorsable.md → modules/develop/pages/endorsable.adoc} +31 -25
- data/docs/{advanced/fixing_locales.md → modules/develop/pages/fixing_locales.adoc} +36 -23
- data/docs/{advanced/followers.md → modules/develop/pages/followable.adoc} +9 -8
- data/docs/modules/develop/pages/guide.adoc +16 -0
- data/docs/modules/develop/pages/guide_architecture.adoc +17 -0
- data/docs/modules/develop/pages/guide_changelog.adoc +8 -0
- data/docs/modules/develop/pages/guide_commands.adoc +86 -0
- data/docs/modules/develop/pages/guide_development_app.adoc +44 -0
- data/docs/modules/develop/pages/guide_development_with_custom_seed_data.adoc +31 -0
- data/docs/modules/develop/pages/guide_development_with_localhost_ssl.adoc +63 -0
- data/docs/modules/develop/pages/guide_example_apps.adoc +59 -0
- data/docs/modules/develop/pages/guide_git_conventions.adoc +75 -0
- data/docs/modules/develop/pages/guide_github_projects.adoc +42 -0
- data/docs/modules/develop/pages/guide_semver.adoc +7 -0
- data/docs/{advanced/how_to_fix_metrics.md → modules/develop/pages/how_to_fix_metrics.adoc} +76 -59
- data/docs/modules/develop/pages/machine_translations.adoc +42 -0
- data/docs/modules/develop/pages/managing_translations_i18n.adoc +24 -0
- data/docs/modules/develop/pages/maps.adoc +499 -0
- data/docs/modules/develop/pages/metrics.adoc +119 -0
- data/docs/{advanced/modules.md → modules/develop/pages/modules.adoc} +16 -6
- data/docs/{advanced/newsletter_templates.md → modules/develop/pages/newsletter_templates.adoc} +12 -10
- data/docs/{advanced/notifications.md → modules/develop/pages/notifications.adoc} +40 -38
- data/docs/{advanced/open-data.md → modules/develop/pages/open-data.adoc} +4 -3
- data/docs/modules/develop/pages/permissions.adoc +92 -0
- data/docs/{advanced/profiling.md → modules/develop/pages/profiling.adoc} +15 -12
- data/docs/modules/develop/pages/releases.adoc +148 -0
- data/docs/modules/develop/pages/reportable.adoc +31 -0
- data/docs/modules/develop/pages/security.adoc +33 -0
- data/docs/{advanced/share_tokens.md → modules/develop/pages/share_tokens.adoc} +18 -14
- data/docs/{advanced/templates.md → modules/develop/pages/templates.adoc} +14 -12
- data/docs/{advanced/testing.md → modules/develop/pages/testing.adoc} +21 -20
- data/docs/{advanced/activity_log.md → modules/develop/pages/traceable.adoc} +31 -26
- data/docs/modules/develop/pages/turbolinks.adoc +7 -0
- data/docs/{advanced/view_hooks.md → modules/develop/pages/view_hooks.adoc} +29 -23
- data/docs/modules/develop/pages/view_models_aka_cells.adoc +105 -0
- data/docs/modules/install/pages/checklist.adoc +39 -0
- data/docs/modules/install/pages/index.adoc +148 -0
- data/docs/{manual-installation.md → modules/install/pages/manual.adoc} +54 -42
- data/docs/modules/install/pages/update.adoc +95 -0
- data/docs/{services/activejob.md → modules/services/pages/activejob.adoc} +3 -3
- data/docs/modules/services/pages/elections_bulletin_board.adoc +52 -0
- data/docs/{services/etherpad.md → modules/services/pages/etherpad.adoc} +15 -12
- data/docs/modules/services/pages/maps.adoc +311 -0
- data/docs/modules/services/pages/smtp.adoc +10 -0
- data/docs/modules/services/pages/social_providers.adoc +122 -0
- data/lib/decidim/gem_manager.rb +5 -5
- data/lib/decidim/version.rb +1 -1
- metadata +137 -100
- data/README.md +0 -157
- data/docs/advanced/add_authorizable_action.md +0 -63
- data/docs/advanced/adding_fixtures_aka_dummy_content.md +0 -9
- data/docs/advanced/data-picker.md +0 -83
- data/docs/advanced/deploy.md +0 -9
- data/docs/advanced/how_to_create_a_module.md +0 -9
- data/docs/advanced/machine_translation_service.md +0 -12
- data/docs/advanced/managing_translations_i18n.md +0 -24
- data/docs/advanced/metrics.md +0 -114
- data/docs/advanced/permissions.md +0 -23
- data/docs/advanced/releases.md +0 -114
- data/docs/advanced/tradeoffs.md +0 -14
- data/docs/advanced/view_models_aka_cells.md +0 -99
- data/docs/checklist.md +0 -55
- data/docs/customization/authorizations.md +0 -5
- data/docs/customization/images.md +0 -7
- data/docs/customization/javascript.md +0 -9
- data/docs/customization/machine_translations.md +0 -30
- data/docs/customization/maps.md +0 -610
- data/docs/customization/oauth.md +0 -50
- data/docs/customization/styles.md +0 -11
- data/docs/customization/texts.md +0 -27
- data/docs/customization/users_registration_mode.md +0 -17
- data/docs/development_guide.md +0 -166
- data/docs/getting_started.md +0 -191
- data/docs/possible_flows_for_proposal.png +0 -0
- data/docs/services/analytics.md +0 -23
- data/docs/services/elections_bulletin_board.md +0 -38
- data/docs/services/maps.md +0 -362
- data/docs/services/social_providers.md +0 -98
@@ -0,0 +1,42 @@
|
|
1
|
+
[plantuml]
|
2
|
+
....
|
3
|
+
@startuml
|
4
|
+
!includeurl https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/v2.0.1/C4_Container.puml
|
5
|
+
|
6
|
+
' uncomment the following line to make proposals
|
7
|
+
'LAYOUT_AS_SKETCH()
|
8
|
+
|
9
|
+
title System Container diagram for Decidim Applications (https://decidim.org)
|
10
|
+
|
11
|
+
|
12
|
+
Person_Ext(visitor_user, "Visitor User", "Anonymous, non registered user.")
|
13
|
+
Person(participant_user, "Participant User", "A registered user. Could also be verified.")
|
14
|
+
Person(administration_user, "Administration User", "A registered user with special permissions.")
|
15
|
+
|
16
|
+
System_Boundary(decidim_system, "decidim"){
|
17
|
+
Container(web_app, "Web Application", "Ruby on Rails 5.2", "Allows participants to make decisions collaboratively through participatory processes, assemblies, consultations, initiatives, etc.")
|
18
|
+
ContainerDb(rel_db, "Relational Database", "PostgreSQL 9.5.x", "Stores users, participatory processes, assemblies, consultations, initiatives, proposals, meetings, etc.")
|
19
|
+
Container(filesystem, "File System", "Local or remote", "Stores uploads (images, documents, etc.)")
|
20
|
+
Container(worker, "Worker", "Ruby on Rails 5.2", "ActiveJob queues for non syncronuos jobs. Works for open data requests, sending emails, etc.")
|
21
|
+
}
|
22
|
+
|
23
|
+
System_Ext(decidim_bulletin_board_system, "Decidim Bulletin Board", "Allows participants to cast end-to-end verifiable secret votes.")
|
24
|
+
System_Ext(mail_system, "SMTP system (e-mail)", "Sends mails to users, like confirmations, reminders, notifications, etc.")
|
25
|
+
System_Ext(etherpad_system, "Etherpad-Lite system", "Optional. Allows real-time text edition in Meetings.")
|
26
|
+
System_Ext(geocoding_system, "Geocoding system", "Optional. An Open Street Maps provider, allows geographical localization of Proposals and Meetings..")
|
27
|
+
System_Ext(oauth_system, "OAUTH2 System", "Optional. Third party sign on systems. Could be Twitter, Facebook, Google or any other OAUTH2 providers.")
|
28
|
+
|
29
|
+
Rel(visitor_user, web_app, "Uses")
|
30
|
+
Rel(participant_user, web_app, "Uses")
|
31
|
+
Rel(administration_user, web_app, "Uses")
|
32
|
+
Rel_Back(participant_user, mail_system, "Sends e-mails to")
|
33
|
+
Rel_Back(administration_user, mail_system, "Sends e-mails to")
|
34
|
+
Rel_Back_Neighbor(decidim_bulletin_board_system, web_app, "Uses")
|
35
|
+
Rel_Neighbor(worker, mail_system, "Sends e-mails", "SMTP")
|
36
|
+
Rel(web_app, rel_db, "Uses")
|
37
|
+
Rel(web_app, filesystem, "Uses")
|
38
|
+
Rel(web_app, oauth_system, "Uses")
|
39
|
+
Rel(web_app, geocoding_system, "Uses")
|
40
|
+
Rel(web_app, etherpad_system, "Embeds", "Through an Iframe")
|
41
|
+
@enduml
|
42
|
+
....
|
@@ -0,0 +1,35 @@
|
|
1
|
+
[plantuml]
|
2
|
+
....
|
3
|
+
@startuml
|
4
|
+
!includeurl https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/v2.0.1/C4_Context.puml
|
5
|
+
|
6
|
+
' uncomment the following line to make proposals
|
7
|
+
'LAYOUT_AS_SKETCH()
|
8
|
+
|
9
|
+
title System Context diagram for Decidim Applications (https://decidim.org)
|
10
|
+
|
11
|
+
|
12
|
+
Person_Ext(visitor_user, "Visitor User", "Anonymous, non registered user.")
|
13
|
+
Person(participant_user, "Participant User", "A registered user. Could also be verified.")
|
14
|
+
Person(administration_user, "Administration User", "A registered user with special permissions.")
|
15
|
+
|
16
|
+
System(decidim_system, "Decidim", "Allows participants to make decisions collaboratively through participatory processes, assemblies, consultations, initiatives, etc.")
|
17
|
+
|
18
|
+
System_Ext(decidim_bulletin_board_system, "Decidim Bulletin Board", "Allows participants to cast end-to-end verifiable secret votes.")
|
19
|
+
System_Ext(mail_system, "SMTP system (e-mail)", "Sends mails to users, like confirmations, reminders, notifications, etc.")
|
20
|
+
System_Ext(etherpad_system, "Etherpad-Lite system", "Optional. Allows real-time text edition in Meetings.")
|
21
|
+
System_Ext(geocoding_system, "Geocoding system", "Optional. An Open Street Maps provider, allows geographical localization of Proposals and Meetings..")
|
22
|
+
System_Ext(oauth_system, "OAUTH2 System", "Optional. Third party sign on systems. Could be Twitter, Facebook, Google or any other OAUTH2 providers.")
|
23
|
+
|
24
|
+
Rel(visitor_user, decidim_system, "Uses")
|
25
|
+
Rel(participant_user, decidim_system, "Uses")
|
26
|
+
Rel(administration_user, decidim_system, "Uses")
|
27
|
+
Rel_Back(participant_user, mail_system, "Sends e-mails to")
|
28
|
+
Rel_Back(administration_user, mail_system, "Sends e-mails to")
|
29
|
+
Rel_Back_Neighbor(decidim_bulletin_board_system, decidim_system, "Uses")
|
30
|
+
Rel_Neighbor(decidim_system, mail_system, "Sends e-mails", "SMTP")
|
31
|
+
Rel(decidim_system, oauth_system, "Uses")
|
32
|
+
Rel(decidim_system, geocoding_system, "Uses")
|
33
|
+
Rel(decidim_system, etherpad_system, "Embeds", "Through an Iframe")
|
34
|
+
@enduml
|
35
|
+
....
|
@@ -1,20 +1,32 @@
|
|
1
|
-
|
1
|
+
= Components
|
2
2
|
|
3
|
-
Components are the core contract between external modules and the core. They're used to define pieces of functionality that are pluggable to participatory spaces and can be enabled or disabled by the administrator.
|
3
|
+
Components are the core contract between external xref:develop:modules.adoc[modules] and the core. They're used to define pieces of functionality that are pluggable to participatory spaces and can be enabled or disabled by the administrator.
|
4
4
|
|
5
|
-
|
5
|
+
== Creating a new component
|
6
6
|
|
7
|
-
|
7
|
+
If you want to create a new component, you can use https://github.com/decidim/decidim/tree/develop/decidim-generators[decidim-generators] to
|
8
|
+
automatically generate a decidim component skeleton, or copy the basic structure
|
9
|
+
of an existing mantained plugin.
|
10
|
+
|
11
|
+
[source,console]
|
12
|
+
----
|
13
|
+
decidim --component engine_name
|
14
|
+
----
|
15
|
+
|
16
|
+
Components are just gems with one or more Rails engines included in it. You can use as an example https://github.com/decidim/decidim/tree/develop/decidim-pages[decidim-pages].
|
8
17
|
|
9
18
|
Check out the `lib/decidim/pages` folder: It includes several files, the most important of which is `component.rb`.
|
10
19
|
|
11
|
-
|
20
|
+
Upload the component to GitHub with the naming *decidim-module-engine_name*, so it's easier to find on the https://github.com/decidim/decidim/network/dependents[dependency graph].
|
21
|
+
|
22
|
+
== Defining a component manifest
|
12
23
|
|
13
24
|
Components are defined in a manifest, along with its engine and admin engine counterpart.
|
14
25
|
|
15
26
|
There's a DSL available to describe all this:
|
16
27
|
|
17
|
-
|
28
|
+
[source,ruby]
|
29
|
+
----
|
18
30
|
# :my_component is the unique name of the component that will be globally registered.
|
19
31
|
Decidim.register_component(:my_component) do |component|
|
20
32
|
# The user will be redirected to the component's engine when accessing it through
|
@@ -54,12 +66,21 @@ Decidim.register_component(:my_component) do |component|
|
|
54
66
|
|
55
67
|
exports.serializer MyComponent::ResourceSerializer
|
56
68
|
end
|
69
|
+
|
70
|
+
# Import definitions allow data to be imported into a component.
|
71
|
+
#
|
72
|
+
# For now supported formats for imports are CSV, JSON and Excel (.xls).
|
73
|
+
# Every resource type needs it's own creator, which creates resource
|
74
|
+
# from parsed data.
|
75
|
+
component.imports :component_resources do |imports|
|
76
|
+
imports.creator MyComponent::ResourceCreator
|
77
|
+
end
|
57
78
|
end
|
58
|
-
|
79
|
+
----
|
59
80
|
|
60
81
|
Every model in a component doesn't have to (and should not) know about its parent participatory space, but instead should be scoped to the components.
|
61
82
|
|
62
|
-
|
83
|
+
== Settings
|
63
84
|
|
64
85
|
Components can define settings that modify its behavior. This settings can be defined to be set for the whole life of the component (global settings), or to be set for each different step of the participatory space (step settings).
|
65
86
|
|
@@ -73,7 +94,8 @@ Each attribute defined can be described through properties:
|
|
73
94
|
* `enum` attributes should have a `choices` attributes that list all the possible values. This could be a lambda function.
|
74
95
|
* they can be `readonly` in some cases, throught a lambda function that received the current component within the `context`.
|
75
96
|
|
76
|
-
|
97
|
+
[source,ruby]
|
98
|
+
----
|
77
99
|
# :my_component is the unique name of the component that will be globally registered.
|
78
100
|
Decidim.register_component(:my_component) do |component|
|
79
101
|
...
|
@@ -91,10 +113,25 @@ Decidim.register_component(:my_component) do |component|
|
|
91
113
|
|
92
114
|
...
|
93
115
|
end
|
94
|
-
|
116
|
+
----
|
95
117
|
|
96
118
|
Each setting should have one or more translation texts related for the admin zone:
|
97
119
|
|
98
120
|
* `decidim.components.[component_name].settings.[global|step].[attribute_name]`: Admin label for the setting.
|
99
121
|
* `decidim.components.[component_name].settings.[global|step].[attribute_name]_help`: Additional text with help for the setting use.
|
100
122
|
* `decidim.components.[component_name].settings.[global|step].[attribute_name]_readonly`: Additional text for the setting when it is readonly.
|
123
|
+
|
124
|
+
== Fixtures
|
125
|
+
|
126
|
+
This sections explains how to add dummy content to a development application.
|
127
|
+
|
128
|
+
=== Proposals example
|
129
|
+
|
130
|
+
. In decidim-proposals open `lib/decidim/proposals/component.rb`.
|
131
|
+
. Find the `+component.seeds do...+` block.
|
132
|
+
. Create your dummy content as if you were in a `db/seed.rb` script.
|
133
|
+
|
134
|
+
=== Tips and Tricks
|
135
|
+
|
136
|
+
* Take advantage of the Faker gem, already in decidim.
|
137
|
+
* If you need content for i18n fields, you can use https://github.com/decidim/decidim/blob/develop/decidim-core/lib/decidim/faker/localized.rb[Localizaed], which uses `Faker` internally.
|
@@ -1,11 +1,11 @@
|
|
1
|
-
|
1
|
+
= Content blocks
|
2
2
|
|
3
3
|
Content blocks come from the need of making sortable and configurable layout chunks. The abstraction is similar to view hooks, but content blocks allow the user to manually configure and sort each block. The order and configuration is backed in the database.
|
4
4
|
|
5
5
|
As of today, content blocks can be:
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
* Sorted
|
8
|
+
* Published
|
9
9
|
|
10
10
|
Configuration will come in the near future.
|
11
11
|
|
@@ -13,22 +13,24 @@ Content blocks are defined per scope, and must be unique in that scope. Examples
|
|
13
13
|
|
14
14
|
Content blocks are used in the organization homepage.
|
15
15
|
|
16
|
-
|
16
|
+
== Registering a content block
|
17
17
|
|
18
18
|
Content blocks use the same manifests-registry pattern used in other places around Decidim. Here's how to register them:
|
19
19
|
|
20
|
-
|
20
|
+
[source,ruby]
|
21
|
+
----
|
21
22
|
Decidim.content_blocks.register(:homepage, :stats) do |content_block|
|
22
23
|
content_block.cell "decidim/content_blocks/stats_block"
|
23
24
|
content_block.public_name_key "decidim.content_blocks.stats_block.name"
|
24
25
|
end
|
25
|
-
|
26
|
+
----
|
26
27
|
|
27
28
|
Let's analyze the example. In the first line, we register a content block named `:stats` for the `:homepage` scope. Then we define the name of the `cell` that will be used to render the content block, and we define the i18n key that holds the name for the content block. These are the only required fields to register a content block.
|
28
29
|
|
29
30
|
Note that content blocks need to be registered from an initializer. If you are adding a content block from a module, use this in the `engine.rb` file of your module:
|
30
31
|
|
31
|
-
|
32
|
+
[source,ruby]
|
33
|
+
----
|
32
34
|
module Decidim::MyModule::Engine < ::Rails::Engine
|
33
35
|
# ...
|
34
36
|
|
@@ -40,23 +42,24 @@ module Decidim::MyModule::Engine < ::Rails::Engine
|
|
40
42
|
|
41
43
|
# ...
|
42
44
|
end
|
43
|
-
|
45
|
+
----
|
44
46
|
|
45
|
-
|
47
|
+
== Managing content blocks
|
46
48
|
|
47
|
-
Content blocks registered under the `:homepage` scope can be seen in the admin area, under Settings
|
49
|
+
Content blocks registered under the `:homepage` scope can be seen in the admin area, under Settings \-> Homepage. You need to be an organization admin in order to enter this section.
|
48
50
|
|
49
51
|
You'll see all the registered content blocks for the `:homepage` scope, those active and those inactive. You can reorder blocks and (un)publish them.
|
50
52
|
|
51
53
|
Another use for content blocks, for example, can be seen at the newsletter templates system.
|
52
54
|
|
53
|
-
|
55
|
+
== Rendering content blocks
|
54
56
|
|
55
57
|
You can check the code we use in the homepage to render them, or use something like this:
|
56
58
|
|
57
|
-
|
59
|
+
[source,ruby]
|
60
|
+
----
|
58
61
|
<% Decidim::ContentBlock.published.for_scope(:homepage, organization: current_organization).each do |content_block| %>
|
59
62
|
<% next unless content_block.manifest %>
|
60
63
|
<%= cell content_block.manifest.cell %>
|
61
64
|
<% end %>
|
62
|
-
|
65
|
+
----
|
@@ -1,25 +1,27 @@
|
|
1
|
-
|
1
|
+
= Content processors
|
2
2
|
|
3
3
|
A content processor is a concept to refer to a set of two classes: a content parser class and a content renderer class.
|
4
4
|
|
5
5
|
The content parser class is used to process the text before it is saved to the database, and the associated renderer class is used to render the saved content.
|
6
6
|
|
7
|
-
|
7
|
+
== How do I add a content processor?
|
8
8
|
|
9
9
|
Register the content processor in an `initializer`:
|
10
10
|
|
11
|
-
|
11
|
+
[source,ruby]
|
12
|
+
----
|
12
13
|
Decidim.content_processors += [:special_words]
|
13
|
-
|
14
|
+
----
|
14
15
|
|
15
16
|
This symbol will be used to instantiate parsers and processors using the following convention:
|
16
17
|
|
17
|
-
|
18
|
-
|
18
|
+
* "Decidim::ContentParsers::#{type.to_s.camelize}Parser"
|
19
|
+
* "Decidim::ContentRenderers::#{type.to_s.camelize}Renderer"
|
19
20
|
|
20
21
|
Autoload parser and renderer if in the lib/ dir. For example if in proposals module edit `lib/decidim/proposals.rb`:
|
21
22
|
|
22
|
-
|
23
|
+
[source,rb]
|
24
|
+
----
|
23
25
|
module Decidim
|
24
26
|
...
|
25
27
|
module ContentParsers
|
@@ -30,11 +32,12 @@ module Decidim
|
|
30
32
|
end
|
31
33
|
...
|
32
34
|
end
|
33
|
-
|
35
|
+
----
|
34
36
|
|
35
37
|
Declare the parser class:
|
36
38
|
|
37
|
-
|
39
|
+
[source,rb]
|
40
|
+
----
|
38
41
|
class Decidim::ContentParsers::SpecialWordsParser < BaseParser
|
39
42
|
Metadata = Struct.new(:count)
|
40
43
|
|
@@ -46,33 +49,36 @@ class Decidim::ContentParsers::SpecialWordsParser < BaseParser
|
|
46
49
|
Metadata.new(content.scan('foo').size)
|
47
50
|
end
|
48
51
|
end
|
49
|
-
|
52
|
+
----
|
50
53
|
|
51
54
|
And the renderer class:
|
52
55
|
|
53
|
-
|
56
|
+
[source,rb]
|
57
|
+
----
|
54
58
|
class Decidim::ContentRenderers::SpecialWordsRenderer < BaseRenderer
|
55
59
|
def render
|
56
60
|
content.gsub(/\~\~(.*?)\~\~/, '<del>\1</del>')
|
57
61
|
end
|
58
62
|
end
|
59
|
-
|
63
|
+
----
|
60
64
|
|
61
|
-
|
65
|
+
== How to use the content parser class
|
62
66
|
|
63
|
-
|
67
|
+
[source,rb]
|
68
|
+
----
|
64
69
|
parser = Decidim::ContentParsers::SpecialWordsParser.new(content, {})
|
65
70
|
parser.rewrite # returns the content rewritten
|
66
71
|
parser.metadata # returns a Metadata object
|
67
|
-
|
72
|
+
----
|
68
73
|
|
69
|
-
|
74
|
+
== How to use the content renderer class
|
70
75
|
|
71
|
-
|
76
|
+
[source,rb]
|
77
|
+
----
|
72
78
|
renderer = Decidim::ContentRenderers::SpecialWordsRenderer.new(content)
|
73
79
|
parser.render # returns the content formatted
|
74
|
-
|
80
|
+
----
|
75
81
|
|
76
|
-
|
82
|
+
== Additional documentation
|
77
83
|
|
78
84
|
You can check the docs in the base classes and the user processor.
|
@@ -0,0 +1,85 @@
|
|
1
|
+
= Data Picker
|
2
|
+
|
3
|
+
Simple HTML ``select``s are not usable enough for the big collections of data Decidim has. We tried using `select2`, but we found problems with its usage and responsiveness, so we moved to a custom data picker. Also, there are many kinds of data that can be selected and many better usable ways to select this data than the simple select provided by html.
|
4
|
+
|
5
|
+
Current Decidim's selector is inspired on https://medium.com/@mibosc/responsive-design-why-and-how-we-ditched-the-good-old-select-element-bc190d62eff5[this] article.
|
6
|
+
|
7
|
+
Data Picker is a selector thought to be reusable in many contexts and kinds of data. The idea behind it is a reusable widget that opens a popup where the user will perform a given selection and then return to the main page. The popup is accompained by a semitransparent layer behind it to blur the background and keep the user concentrated in the current action, the selection.
|
8
|
+
|
9
|
+
== Artifacts
|
10
|
+
|
11
|
+
Data Picker is composed by 2 visual artifacts, plus the javascript and one controller action for each selection type:
|
12
|
+
|
13
|
+
* *widget*: the first visual artifact is the widget that encapsulates the main Data Picker functionality. This widget manages the rendering of *the button* that opens the selector and *the popup*. This button is managed via ujs (Unobtrusive JavaScript). The popup is empty and must be filled with a selection partial.
|
14
|
+
* *selection functionality* partial: There are many ways to select things (and many kinds of things to select). Thus, the selection functionality can be customized via a selection partial which will be rendered inside the widget's popup. This partial is supplied to the widget via ajax.
|
15
|
+
* *controller ajax action*: An ajax action will send the content of the popup in an html partial.
|
16
|
+
|
17
|
+
== How to
|
18
|
+
|
19
|
+
=== Placing the Data Picker widget
|
20
|
+
|
21
|
+
The Data Picker widget structure is as follows:
|
22
|
+
|
23
|
+
[source,html]
|
24
|
+
----
|
25
|
+
<div id="some-unique-id" class="data-picker <%= picker_options[:class]%>" data-picker-name="<%=picker_options[:name]%>">
|
26
|
+
<div class="picker-values"><% @form.proposals.each do |proposal, params| %>
|
27
|
+
<div><a href="<%= prompt_params[:url] %>" data-picker-value="<%=proposal%>"><%=proposal%></a></div>
|
28
|
+
<% end %></div>
|
29
|
+
<div class="picker-prompt"><a href="<%= prompt_params[:url] %>"><%= prompt_params[:text] %></a></div>
|
30
|
+
</div>
|
31
|
+
----
|
32
|
+
|
33
|
+
Placing the widget in a form requires two steps:
|
34
|
+
|
35
|
+
It is a good way to implement the widget to think that it is a component that takes parameters.
|
36
|
+
|
37
|
+
. Prepare Data Picker parameters
|
38
|
+
Data Picker takes two arguments the `picker_params` hash (to fill the main div) and the `prompt_params` hash (for the `picker-prompt` div).
|
39
|
+
** `picker_params.id`: the html unique id of the widget instance, required by the JavaScript.
|
40
|
+
** `picker_params.name`: the html name of the widget which will be sent by the form.
|
41
|
+
** `picker_params.class`: one of `picker-multiple`, when user can select multiple data, or `picker-single`, when only one data is to be selected.
|
42
|
+
. Html for the Data Picker widget
|
43
|
+
|
44
|
+
=== Selector popup content
|
45
|
+
|
46
|
+
*Anchors* in the selector can have the following attributes:
|
47
|
+
|
48
|
+
* data-close: this anchor will be ignored and will close the picker
|
49
|
+
* href: the url to be used for choosing
|
50
|
+
* picker-choose: when not present the picker will navigate as a regular anchor. Otherwise a choose action in the component is invoked with params: `url: href, value: picker-value, text: picker-text`.
|
51
|
+
* picker-value: the selected value
|
52
|
+
* picker-text (optional): The text to be shown in the picker button.
|
53
|
+
|
54
|
+
This is an example of a link used to choose an element:
|
55
|
+
|
56
|
+
[source,html]
|
57
|
+
----
|
58
|
+
<a class="button" href="[picker path browsing this element]" data-picker-text="[text]" data-picker-value="[value]" data-picker-choose>[text]</a>
|
59
|
+
----
|
60
|
+
|
61
|
+
*Checkboxes* also can be used in the selector, to allow to select several values at once. In this case, the `href` attribute is replaced with `data-picker-url` and the `data-picker-value` attribute is replaced with the `value` built-in attribute.
|
62
|
+
|
63
|
+
This is an example of a checkbox that allow to choose an element without closing the picker:
|
64
|
+
|
65
|
+
[source,html]
|
66
|
+
----
|
67
|
+
<label><input type="checkbox" data-picker-url="[picker path browsing this element]" data-picker-text="[text]" value="[value]" data-picker-choose>[text]</label>
|
68
|
+
----
|
69
|
+
|
70
|
+
== Examples of use of the DataPicker
|
71
|
+
|
72
|
+
* Scopes picker: Allows to browse the tree of scopes and select one or several scopes.
|
73
|
+
** link:../../decidim-core/lib/decidim/form_builder.rb[FormBuilder scopes picker field]: Basic method to render a scope picker for a form.
|
74
|
+
** link:../../decidim-core/lib/decidim/filter_form_builder.rb[FilterFormBuilder scopes picker field]: Basic method to render a scope picker for a filter form.
|
75
|
+
** link:../../decidim-core/app/helpers/decidim/scopes_helper.rb[Scopes pickers helpers]: Helpers to simplify the call to basic methods.
|
76
|
+
** link:../../decidim-core/app/controllers/decidim/scopes_controller.rb[Global scopes picker controller]: Controller used to browse the scopes on a picker in any part of the application.
|
77
|
+
** link:../../decidim-proposals/app/views/decidim/proposals/proposals/_edit_form_fields.html.erb[Proposals' frontend form using a scopes picker]: Use of a scope picker helper on a frontend page.
|
78
|
+
** link:../../decidim-proposals/app/views/decidim/proposals/admin/proposals/_form.html.erb[Proposals' admin form using a scopes picker]: Use of a scope picker helper on an admin page.
|
79
|
+
** link:../../decidim-meetings/app/views/decidim/meetings/meetings/_filters.html.erb[Meetings' multiple scopes picker for filtering]: Use of a multiple scopes picker on a filter form.
|
80
|
+
* Proposals picker: Allows to search and select multiple proposals to be referenced from other components.
|
81
|
+
** link:../../decidim-proposals/app/helpers/decidim/proposals/admin/proposals_picker_helper.rb[Proposals pickers helper]: Helper to render a DataPicker for proposals selection.
|
82
|
+
** link:../../decidim-proposals/app/controllers/concerns/decidim/proposals/admin/picker.rb[Proposals picker concern for admin pages]: You will need to add this concern to your controller, add a route for `proposals_picker` endpoint and create a view for it to show the proposals picker in your component context.
|
83
|
+
** link:../../decidim-proposals/app/cells/decidim/proposals/proposals_picker_cell.rb[Proposals picker cell]: You can use this cell to reuse the logic in your picker view.
|
84
|
+
** link:../../decidim-accountability/app/controllers/decidim/accountability/admin/results_controller.rb[Accountability's admin controller with a proposals picker]: It only needs to add the concern (and the endpoint to the routes).
|
85
|
+
** link:../../decidim-accountability/app/views/decidim/accountability/admin/results/proposals_picker.html.erb[Accountability's admin view with a proposals picker]: It only needs to render the cell.
|
@@ -0,0 +1,15 @@
|
|
1
|
+
= Deploy
|
2
|
+
|
3
|
+
== Self-hosted
|
4
|
+
|
5
|
+
You can install Decidim like a regular Ruby on Rails application, with nginx, Passenger, rbenv and PostgreSQL. You should also configure a valid SMTP account to send emails and add the delayed_job gem and execute it so you can receive emails (ie on user registration).
|
6
|
+
|
7
|
+
== Heroku
|
8
|
+
|
9
|
+
You can follow an opinionated Rails generator to configure your decidim app so that it can be https://github.com/codegram/decidim-deploy-heroku[deployed to Heroku].
|
10
|
+
|
11
|
+
== Docker
|
12
|
+
|
13
|
+
You can also deploy a Decidim app using Docker on hosting services that support it like Dokku, Heroku and all the cloud providers.
|
14
|
+
|
15
|
+
See the xref:develop:docker.adoc[Decidim on Docker doc] for more details.
|