decidim-core 0.4.4 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/config/decidim_core_manifest.js +1 -0
- data/app/assets/images/decidim/icons.svg +1 -1
- data/app/assets/javascripts/decidim.js.es6 +3 -0
- data/app/assets/javascripts/decidim/form_filter.component.js.es6 +39 -6
- data/app/assets/javascripts/decidim/form_filter.component.test.js +13 -10
- data/app/assets/javascripts/decidim/impersonation.js.es6 +16 -0
- data/app/assets/javascripts/decidim/select2.field.js.es6 +47 -0
- data/app/assets/javascripts/decidim/select2.js.es6 +8 -0
- data/app/assets/stylesheets/decidim/_decidim.scss +3 -0
- data/app/assets/stylesheets/decidim/extras/_announcement.scss +3 -0
- data/app/assets/stylesheets/decidim/extras/_callout.scss +1 -1
- data/app/assets/stylesheets/decidim/extras/_impersonation-bar.scss +22 -0
- data/app/assets/stylesheets/decidim/extras/_process_stats.scss +1 -1
- data/app/assets/stylesheets/decidim/extras/_proposal_form.scss +7 -0
- data/app/assets/stylesheets/decidim/extras/_reference.scss +1 -1
- data/app/assets/stylesheets/decidim/extras/_register_form.scss +1 -1
- data/app/assets/stylesheets/decidim/extras/_social_icons_mini.scss +1 -1
- data/app/assets/stylesheets/decidim/layouts/_home.scss +1 -1
- data/app/assets/stylesheets/decidim/layouts/_view.scss +1 -1
- data/app/assets/stylesheets/decidim/map.css +1 -1
- data/app/assets/stylesheets/decidim/modules/_author-avatar.scss +1 -1
- data/app/assets/stylesheets/decidim/modules/_callout.scss +1 -1
- data/app/assets/stylesheets/decidim/modules/_datepicker.scss +1 -1
- data/app/assets/stylesheets/decidim/modules/_definition-data.scss +1 -1
- data/app/assets/stylesheets/decidim/modules/_extra.scss +1 -1
- data/app/assets/stylesheets/decidim/modules/_flag.scss +1 -1
- data/app/assets/stylesheets/decidim/modules/_footer.scss +1 -1
- data/app/assets/stylesheets/decidim/modules/_forms.scss +1 -1
- data/app/assets/stylesheets/decidim/modules/_help.scss +1 -1
- data/app/assets/stylesheets/decidim/modules/_pagination.scss +1 -1
- data/app/assets/stylesheets/decidim/modules/_process-info.scss +1 -1
- data/app/assets/stylesheets/decidim/modules/_reference.scss +1 -1
- data/app/assets/stylesheets/decidim/modules/_reveal.scss +1 -1
- data/app/assets/stylesheets/decidim/modules/_signup.scss +1 -1
- data/app/assets/stylesheets/decidim/modules/_static-pages.scss +1 -1
- data/app/assets/stylesheets/decidim/modules/_tags.scss +1 -1
- data/app/assets/stylesheets/decidim/modules/_title-action.scss +1 -1
- data/app/assets/stylesheets/decidim/modules/_user-form.scss +1 -1
- data/app/assets/stylesheets/decidim/modules/_video.scss +1 -1
- data/app/assets/stylesheets/decidim/plugins/_select2.scss +63 -0
- data/app/assets/stylesheets/decidim/utils/_toggle-expand.scss +1 -1
- data/app/commands/decidim/invite_user.rb +5 -2
- data/app/controllers/concerns/decidim/devise_controllers.rb +6 -0
- data/app/controllers/concerns/decidim/impersonate_users.rb +67 -0
- data/app/controllers/concerns/decidim/needs_authorization.rb +0 -4
- data/app/controllers/decidim/application_controller.rb +7 -0
- data/app/controllers/decidim/devise/invitations_controller.rb +7 -0
- data/app/controllers/decidim/errors_controller.rb +1 -1
- data/app/controllers/decidim/features/base_controller.rb +1 -1
- data/app/controllers/decidim/participatory_process_widgets_controller.rb +0 -2
- data/app/controllers/decidim/scopes_controller.rb +29 -0
- data/app/forms/decidim/attachment_form.rb +14 -0
- data/app/forms/decidim/invite_user_form.rb +12 -1
- data/app/helpers/decidim/application_helper.rb +1 -0
- data/app/helpers/decidim/attachments_helper.rb +11 -0
- data/app/helpers/decidim/decidim_form_helper.rb +9 -8
- data/app/helpers/decidim/icon_helper.rb +12 -2
- data/app/helpers/decidim/participatory_process_helper.rb +0 -24
- data/app/helpers/decidim/scopes_helper.rb +15 -0
- data/app/helpers/decidim/translations_helper.rb +1 -1
- data/app/mailers/decidim/reported_mailer.rb +1 -1
- data/app/models/decidim/abilities/admin_ability.rb +1 -0
- data/app/models/decidim/abilities/everyone_ability.rb +2 -0
- data/app/models/decidim/abilities/user_manager_ability.rb +35 -0
- data/app/models/decidim/impersonation_log.rb +35 -0
- data/app/models/decidim/organization.rb +9 -0
- data/app/models/decidim/participatory_process.rb +1 -4
- data/app/models/decidim/scope.rb +65 -1
- data/app/models/decidim/scope_type.rb +16 -0
- data/app/models/decidim/user.rb +35 -4
- data/app/presenters/decidim/participatory_process_stats_presenter.rb +1 -1
- data/app/queries/decidim/freetext_scopes.rb +39 -0
- data/app/services/decidim/resource_search.rb +7 -6
- data/app/uploaders/decidim/attachment_uploader.rb +1 -1
- data/app/views/decidim/account/delete.html.erb +1 -1
- data/app/views/decidim/application/_documents.html.erb +4 -2
- data/app/views/decidim/participatory_processes/_statistics.html.erb +1 -1
- data/app/views/decidim/participatory_processes/show.html.erb +4 -0
- data/app/views/decidim/reported_mailer/hide.html.erb +1 -1
- data/app/views/decidim/reported_mailer/report.html.erb +1 -1
- data/app/views/decidim/shared/_announcement.html.erb +5 -0
- data/app/views/decidim/shared/_feature_announcement.html.erb +5 -0
- data/app/views/decidim/shared/_flag_modal.html.erb +1 -1
- data/app/views/decidim/shared/_tags.html.erb +10 -0
- data/app/views/devise/mailer/invitation_instructions.html.erb +13 -0
- data/app/views/devise/mailer/invitation_instructions.text.erb +11 -0
- data/app/views/layouts/decidim/_application.html.erb +1 -0
- data/app/views/layouts/decidim/_impersonation_warning.html.erb +10 -0
- data/app/views/layouts/decidim/_wrapper.html.erb +1 -1
- data/app/views/pages/home/_statistics.html.erb +1 -1
- data/app/views/pages/home/_sub_hero.html.erb +1 -1
- data/config/locales/ca.yml +10 -1
- data/config/locales/en.yml +9 -0
- data/config/locales/es.yml +10 -1
- data/config/locales/eu.yml +22 -1
- data/config/locales/fi.yml +1 -1
- data/config/locales/fr.yml +60 -0
- data/config/locales/it.yml +1 -1
- data/config/locales/nl.yml +1 -1
- data/config/locales/pl.yml +91 -0
- data/config/routes.rb +2 -0
- data/db/migrate/20170605162500_add_hierarchy_to_scopes.rb +70 -0
- data/db/migrate/20170713131206_add_admin_to_users.rb +6 -1
- data/db/migrate/20170713131308_migrate_user_roles_to_participatory_process_roles.rb +5 -1
- data/db/migrate/20170720135441_add_managed_to_users.rb +7 -0
- data/db/migrate/20170720140610_set_email_unique_in_organization_condition_for_managed_users.rb +12 -0
- data/db/migrate/20170724130558_create_impersonation_logs.rb +15 -0
- data/db/migrate/20170727125445_add_roles_to_users.rb +7 -0
- data/db/migrate/20170804125402_attachment_description_nullable.rb +7 -0
- data/db/migrate/20170808080905_add_announcement_to_participatory_processes.rb +7 -0
- data/db/migrate/20170809084005_add_scopes_enabled_to_participatory_processes.rb +7 -0
- data/db/seeds.rb +34 -10
- data/lib/decidim/core.rb +11 -5
- data/lib/decidim/core/engine.rb +1 -0
- data/lib/decidim/core/test.rb +2 -0
- data/lib/decidim/core/test/factories.rb +59 -22
- data/lib/decidim/core/test/shared_examples/announcements_examples.rb +58 -0
- data/lib/decidim/core/test/shared_examples/comments_examples.rb +15 -29
- data/lib/decidim/core/test/shared_examples/errors.rb +1 -1
- data/lib/decidim/core/test/shared_examples/has_attachments.rb +4 -9
- data/lib/decidim/core/test/shared_examples/manage_moderations_examples.rb +1 -8
- data/lib/decidim/core/test/shared_examples/paginated_resource_examples.rb +2 -2
- data/lib/decidim/core/test/shared_examples/process_announcements_examples.rb +33 -0
- data/lib/decidim/core/test/shared_examples/reports_examples.rb +1 -2
- data/lib/decidim/core/version.rb +6 -2
- data/lib/decidim/faker/localized.rb +4 -4
- data/lib/decidim/filter_form_builder.rb +7 -0
- data/lib/decidim/form_builder.rb +34 -5
- data/lib/decidim/scopable.rb +33 -0
- data/lib/decidim/settings_manifest.rb +10 -2
- data/lib/decidim/translatable_attributes.rb +0 -1
- metadata +61 -17
- data/app/helpers/decidim/organization_scopes_helper.rb +0 -42
- data/db/seeds/city3.jpeg +0 -0
- data/lib/tasks/factory_girl.rake +0 -17
@@ -0,0 +1,63 @@
|
|
1
|
+
.select2-container--focus .select2-selection {
|
2
|
+
border: 1px solid $primary !important;
|
3
|
+
}
|
4
|
+
.select2-container {
|
5
|
+
&.select2 {
|
6
|
+
margin-bottom: 1.5rem;
|
7
|
+
}
|
8
|
+
.select2-dropdown {
|
9
|
+
box-shadow: inset 0 -1px 2px rgba(26, 24, 29, 0.1);
|
10
|
+
border-color: #eee;
|
11
|
+
.select2-search__field {
|
12
|
+
margin-bottom: 0;
|
13
|
+
}
|
14
|
+
}
|
15
|
+
.select2-selection {
|
16
|
+
box-shadow: inset 0 1px 2px rgba(26, 24, 29, 0.1);
|
17
|
+
border-color: #eee;
|
18
|
+
}
|
19
|
+
.select2-selection--single {
|
20
|
+
margin-top: 5px;
|
21
|
+
height: 48px;
|
22
|
+
.select2-selection__rendered {
|
23
|
+
line-height: 46px;
|
24
|
+
padding-right: 23px;
|
25
|
+
font-weight: normal;
|
26
|
+
color: #1a181d;
|
27
|
+
}
|
28
|
+
.select2-selection__arrow {
|
29
|
+
height: 54px;
|
30
|
+
right: 5px;
|
31
|
+
b {
|
32
|
+
border-width: 6px 5px 0 5px;
|
33
|
+
border-top-color: #121014;
|
34
|
+
}
|
35
|
+
}
|
36
|
+
}
|
37
|
+
.select2-selection--multiple {
|
38
|
+
.select2-selection__rendered li {
|
39
|
+
border: 1px solid #e8e8e8;
|
40
|
+
padding: 0 .5rem;
|
41
|
+
color: $secondary;
|
42
|
+
background: none;
|
43
|
+
border-radius: 0;
|
44
|
+
font-size: 0.9rem;
|
45
|
+
&.select2-search {
|
46
|
+
clear: left;
|
47
|
+
padding: 0;
|
48
|
+
border: none;
|
49
|
+
.select2-search__field {
|
50
|
+
width: 100% !important;
|
51
|
+
padding: 0.2rem;
|
52
|
+
height: 1.75rem;
|
53
|
+
margin: 0.2rem 0 0;
|
54
|
+
font-size: 1rem;
|
55
|
+
}
|
56
|
+
}
|
57
|
+
}
|
58
|
+
}
|
59
|
+
}
|
60
|
+
.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b {
|
61
|
+
border-width: 0 5px 6px 5px;
|
62
|
+
border-bottom-color: #121014;
|
63
|
+
}
|
@@ -31,7 +31,9 @@ module Decidim
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def update_user
|
34
|
-
user.admin = form.admin
|
34
|
+
user.admin = form.role == "admin"
|
35
|
+
user.roles << form.role if form.role != "admin"
|
36
|
+
user.roles = user.roles.uniq
|
35
37
|
user.save!
|
36
38
|
end
|
37
39
|
|
@@ -40,7 +42,8 @@ module Decidim
|
|
40
42
|
name: form.name,
|
41
43
|
email: form.email.downcase,
|
42
44
|
organization: form.organization,
|
43
|
-
admin: form.admin,
|
45
|
+
admin: form.role == "admin",
|
46
|
+
roles: form.role == "admin" ? [] : [form.role],
|
44
47
|
comments_notifications: true,
|
45
48
|
replies_notifications: true
|
46
49
|
)
|
@@ -26,5 +26,11 @@ module Decidim
|
|
26
26
|
|
27
27
|
layout "layouts/decidim/application"
|
28
28
|
end
|
29
|
+
|
30
|
+
# Overwrites `cancancan`'s method to point to the correct ability class,
|
31
|
+
# since the gem expects the ability class to be in the root namespace.
|
32
|
+
def current_ability_klass
|
33
|
+
Decidim::Abilities::BaseAbility
|
34
|
+
end
|
29
35
|
end
|
30
36
|
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/concern"
|
4
|
+
|
5
|
+
module Decidim
|
6
|
+
# Shared behaviour for controllers that need user impersonation logic.
|
7
|
+
module ImpersonateUsers
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
included do
|
11
|
+
before_action :check_impersonation_log_expired
|
12
|
+
|
13
|
+
helper_method :impersonation_session_ends_at, :impersonation_session_remaining_duration_in_minutes
|
14
|
+
|
15
|
+
alias_method :real_user, :current_user
|
16
|
+
|
17
|
+
# Returns a manager user if the real user has an active impersonation
|
18
|
+
def current_user
|
19
|
+
managed_user || real_user
|
20
|
+
end
|
21
|
+
|
22
|
+
def impersonation_session_ends_at
|
23
|
+
@impersonation_session_ends_at ||= impersonation_log.started_at + Decidim::ImpersonationLog::SESSION_TIME_IN_MINUTES.minutes
|
24
|
+
end
|
25
|
+
|
26
|
+
def impersonation_session_remaining_duration_in_minutes
|
27
|
+
((impersonation_session_ends_at - Time.current) / 60).round
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
# Returns the managed user impersonated by an admin if exists
|
33
|
+
def managed_user
|
34
|
+
return unless can_impersonate_users?
|
35
|
+
impersonation_log&.user
|
36
|
+
end
|
37
|
+
|
38
|
+
# Check if the active impersonation session has expired or not.
|
39
|
+
def check_impersonation_log_expired
|
40
|
+
return unless can_impersonate_users? && impersonation_log
|
41
|
+
|
42
|
+
if impersonation_log.expired?
|
43
|
+
impersonation_log.ended_at = Time.current
|
44
|
+
impersonation_log.save!
|
45
|
+
flash[:alert] = I18n.t("managed_users.expired_session", scope: "decidim")
|
46
|
+
redirect_to decidim_admin.managed_users_path
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Gets the ability instance for the real user logged in.
|
51
|
+
def real_ability
|
52
|
+
@real_ability ||= current_ability_klass.new(real_user, ability_context)
|
53
|
+
end
|
54
|
+
|
55
|
+
def can_impersonate_users?
|
56
|
+
real_user && real_ability.can?(:impersonate, :managed_users)
|
57
|
+
end
|
58
|
+
|
59
|
+
def impersonation_log
|
60
|
+
@impersonation_log ||= Decidim::ImpersonationLog
|
61
|
+
.where(admin: real_user)
|
62
|
+
.active
|
63
|
+
.first
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -7,6 +7,7 @@ module Decidim
|
|
7
7
|
include LocaleSwitcher
|
8
8
|
include NeedsAuthorization
|
9
9
|
include PayloadInfo
|
10
|
+
include ImpersonateUsers
|
10
11
|
|
11
12
|
helper Decidim::MetaTagsHelper
|
12
13
|
helper Decidim::DecidimFormHelper
|
@@ -45,5 +46,11 @@ module Decidim
|
|
45
46
|
def add_vary_header
|
46
47
|
response.headers["Vary"] = "Accept"
|
47
48
|
end
|
49
|
+
|
50
|
+
# Overwrites `cancancan`'s method to point to the correct ability class,
|
51
|
+
# since the gem expects the ability class to be in the root namespace.
|
52
|
+
def current_ability_klass
|
53
|
+
Decidim::Abilities::BaseAbility
|
54
|
+
end
|
48
55
|
end
|
49
56
|
end
|
@@ -18,6 +18,13 @@ module Decidim
|
|
18
18
|
def after_accept_path_for(resource)
|
19
19
|
params[:invite_redirect] || after_sign_in_path_for(resource)
|
20
20
|
end
|
21
|
+
|
22
|
+
# When a managed user accepts the invitation is promoted to non-managed user.
|
23
|
+
def accept_resource
|
24
|
+
resource = resource_class.accept_invitation!(update_resource_params)
|
25
|
+
resource.update_attribute(:managed, false) if resource.managed?
|
26
|
+
resource
|
27
|
+
end
|
21
28
|
end
|
22
29
|
end
|
23
30
|
end
|
@@ -18,7 +18,7 @@ module Decidim
|
|
18
18
|
helper Decidim::ParticipatoryProcessHelper
|
19
19
|
helper Decidim::IconHelper
|
20
20
|
helper Decidim::ResourceHelper
|
21
|
-
helper Decidim::
|
21
|
+
helper Decidim::ScopesHelper
|
22
22
|
helper Decidim::ActionAuthorizationHelper
|
23
23
|
helper Decidim::AttachmentsHelper
|
24
24
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
# Exposes the scopes text search so users can choose a scope writing its name.
|
5
|
+
class ScopesController < Decidim::ApplicationController
|
6
|
+
def search
|
7
|
+
authorize! :search, Scope
|
8
|
+
root = Scope.where(id: params[:root], organization: current_organization).first
|
9
|
+
scopes = if params[:term].present?
|
10
|
+
FreetextScopes.for(current_organization, I18n.locale, params[:term], root)
|
11
|
+
elsif root
|
12
|
+
root.children
|
13
|
+
else
|
14
|
+
current_organization.top_scopes
|
15
|
+
end
|
16
|
+
root_option = if params[:include_root] == "true" && !params[:term].present?
|
17
|
+
if root
|
18
|
+
[{ id: root.id.to_s, text: root.name[I18n.locale.to_s] }]
|
19
|
+
else
|
20
|
+
[{ id: "global", text: I18n.t("decidim.scopes.global") }]
|
21
|
+
end
|
22
|
+
else
|
23
|
+
[]
|
24
|
+
end
|
25
|
+
|
26
|
+
render json: { results: root_option + scopes.map { |scope| { id: scope.id.to_s, text: scope.name[I18n.locale.to_s] } } }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
# A form object used to create attachments.
|
5
|
+
#
|
6
|
+
class AttachmentForm < Form
|
7
|
+
attribute :title, String
|
8
|
+
attribute :file
|
9
|
+
|
10
|
+
mimic :attachment
|
11
|
+
|
12
|
+
validates :title, presence: true, if: ->(form) { form.file.present? }
|
13
|
+
end
|
14
|
+
end
|
@@ -11,9 +11,11 @@ module Decidim
|
|
11
11
|
attribute :invitation_instructions, String
|
12
12
|
attribute :organization, Decidim::Organization
|
13
13
|
attribute :invited_by, Decidim::User
|
14
|
-
attribute :
|
14
|
+
attribute :role, String
|
15
15
|
|
16
16
|
validates :email, :name, :organization, :invitation_instructions, presence: true
|
17
|
+
validates :role, inclusion: { in: Decidim::User::ROLES }
|
18
|
+
|
17
19
|
validate :admin_uniqueness
|
18
20
|
|
19
21
|
def email
|
@@ -28,6 +30,15 @@ module Decidim
|
|
28
30
|
super || current_user
|
29
31
|
end
|
30
32
|
|
33
|
+
def available_roles_for_select
|
34
|
+
Decidim::User::ROLES.map do |role|
|
35
|
+
[
|
36
|
+
I18n.t(role, scope: "decidim.admin.models.user.fields.roles"),
|
37
|
+
role
|
38
|
+
]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
31
42
|
private
|
32
43
|
|
33
44
|
def admin_uniqueness
|
@@ -12,5 +12,16 @@ module Decidim
|
|
12
12
|
def attachments_for(attached_to)
|
13
13
|
render partial: "attachments", locals: { attached_to: attached_to }
|
14
14
|
end
|
15
|
+
|
16
|
+
# Renders the attachment's title.
|
17
|
+
# Checks if the attachment's title is translated or not and use
|
18
|
+
# the correct render method.
|
19
|
+
#
|
20
|
+
# attachment - An Attachment object
|
21
|
+
#
|
22
|
+
# Returns String.
|
23
|
+
def attachment_title(attachment)
|
24
|
+
attachment.title.is_a?(Hash) ? translated_attribute(attachment.title) : attachment.title
|
25
|
+
end
|
15
26
|
end
|
16
27
|
end
|
@@ -57,21 +57,22 @@ module Decidim
|
|
57
57
|
def translated_field_tag(type, object_name, name, value = {}, options = {})
|
58
58
|
locales = available_locales
|
59
59
|
|
60
|
-
|
61
|
-
enabled_tabs = options[:enable_tabs].nil? ? true : options[:enable_tabs]
|
62
|
-
tabs_panels_data = enabled_tabs ? { tabs: true } : {}
|
60
|
+
field_label = label_tag(name, options[:label])
|
63
61
|
|
64
62
|
if locales.count == 1
|
65
|
-
|
63
|
+
field_input = send(
|
66
64
|
type,
|
67
|
-
"#{name}_#{locales.first.to_s.gsub("-", "__")}"
|
68
|
-
options.merge(label: options[:label])
|
65
|
+
"#{name}_#{locales.first.to_s.gsub("-", "__")}"
|
69
66
|
)
|
67
|
+
|
68
|
+
return safe_join [field_label, field_input]
|
70
69
|
end
|
71
70
|
|
72
|
-
|
73
|
-
|
71
|
+
tabs_id = options[:tabs_id] || "#{object_name}-#{name}-tabs"
|
72
|
+
enabled_tabs = options[:enable_tabs].nil? ? true : options[:enable_tabs]
|
73
|
+
tabs_panels_data = enabled_tabs ? { tabs: true } : {}
|
74
74
|
|
75
|
+
label_tabs = content_tag(:div, class: "label--tabs") do
|
75
76
|
tabs_panels = "".html_safe
|
76
77
|
if options[:label] != false
|
77
78
|
tabs_panels = content_tag(:ul, class: "tabs tabs--lang", id: tabs_id, data: tabs_panels_data) do
|