decidim-admin 0.25.2 → 0.26.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-admin might be problematic. Click here for more details.

Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/app/commands/decidim/admin/create_import_example.rb +21 -0
  3. data/app/commands/decidim/admin/create_static_page.rb +9 -3
  4. data/app/commands/decidim/admin/update_organization_appearance.rb +2 -1
  5. data/app/controllers/concerns/decidim/admin/user_groups/filterable.rb +45 -0
  6. data/app/controllers/concerns/decidim/moderated_users/admin/filterable.rb +51 -0
  7. data/app/controllers/decidim/admin/imports_controller.rb +48 -10
  8. data/app/controllers/decidim/admin/moderated_users_controller.rb +2 -2
  9. data/app/controllers/decidim/admin/scopes_controller.rb +2 -1
  10. data/app/controllers/decidim/admin/user_groups_controller.rb +13 -5
  11. data/app/forms/decidim/admin/import_example_form.rb +50 -0
  12. data/app/forms/decidim/admin/import_form.rb +46 -40
  13. data/app/forms/decidim/admin/organization_appearance_form.rb +1 -0
  14. data/app/helpers/decidim/admin/imports_helper.rb +16 -6
  15. data/app/helpers/decidim/admin/resource_scope_helper.rb +9 -0
  16. data/app/helpers/decidim/admin/settings_helper.rb +13 -0
  17. data/app/packs/entrypoints/decidim_admin.js +0 -1
  18. data/app/packs/src/decidim/admin/dynamic_fields.component.js +8 -0
  19. data/app/permissions/decidim/admin/permissions.rb +1 -0
  20. data/app/views/decidim/admin/imports/_dropdown.html.erb +9 -4
  21. data/app/views/decidim/admin/imports/new.html.erb +24 -22
  22. data/app/views/decidim/admin/moderated_users/_report.html.erb +0 -1
  23. data/app/views/decidim/admin/moderated_users/index.html.erb +5 -2
  24. data/app/views/decidim/admin/moderations/_report.html.erb +0 -1
  25. data/app/views/decidim/admin/moderations/index.html.erb +1 -1
  26. data/app/views/decidim/admin/organization_appearance/form/_colors.html.erb +7 -0
  27. data/app/views/decidim/admin/participatory_space_private_users/index.html.erb +12 -4
  28. data/app/views/decidim/admin/user_groups/index.html.erb +8 -44
  29. data/app/views/layouts/decidim/admin/_callouts_full.html.erb +4 -0
  30. data/app/views/layouts/decidim/admin/_title_bar.html.erb +2 -2
  31. data/config/brakeman.ignore +26 -0
  32. data/config/locales/ar.yml +0 -7
  33. data/config/locales/ca.yml +0 -13
  34. data/config/locales/cs.yml +50 -13
  35. data/config/locales/de.yml +8 -13
  36. data/config/locales/el.yml +0 -15
  37. data/config/locales/en.yml +46 -17
  38. data/config/locales/es-MX.yml +0 -13
  39. data/config/locales/es-PY.yml +0 -13
  40. data/config/locales/es.yml +45 -16
  41. data/config/locales/eu.yml +8 -13
  42. data/config/locales/fi-plain.yml +33 -13
  43. data/config/locales/fi.yml +46 -17
  44. data/config/locales/fr-CA.yml +42 -13
  45. data/config/locales/fr.yml +48 -19
  46. data/config/locales/ga-IE.yml +1 -6
  47. data/config/locales/gl.yml +33 -13
  48. data/config/locales/hu.yml +1 -9
  49. data/config/locales/id-ID.yml +0 -7
  50. data/config/locales/is-IS.yml +0 -7
  51. data/config/locales/it.yml +6 -13
  52. data/config/locales/ja.yml +92 -67
  53. data/config/locales/lb-LU.yml +1034 -0
  54. data/config/locales/lb.yml +6 -15
  55. data/config/locales/lv.yml +0 -7
  56. data/config/locales/nl.yml +73 -13
  57. data/config/locales/no.yml +0 -7
  58. data/config/locales/pl.yml +7 -13
  59. data/config/locales/pt-BR.yml +1 -14
  60. data/config/locales/pt.yml +8 -15
  61. data/config/locales/ro-RO.yml +40 -16
  62. data/config/locales/ru.yml +0 -7
  63. data/config/locales/sk.yml +0 -7
  64. data/config/locales/sr-CS.yml +0 -6
  65. data/config/locales/sv.yml +33 -13
  66. data/config/locales/tr-TR.yml +0 -7
  67. data/config/locales/uk.yml +0 -7
  68. data/config/locales/val-ES.yml +14 -0
  69. data/config/locales/zh-CN.yml +0 -7
  70. data/lib/decidim/admin/engine.rb +5 -0
  71. data/lib/decidim/admin/form_builder.rb +8 -1
  72. data/lib/decidim/admin/import/creator.rb +32 -12
  73. data/lib/decidim/admin/import/importer.rb +32 -14
  74. data/lib/decidim/admin/import/readers/base.rb +23 -0
  75. data/lib/decidim/admin/import/readers/csv.rb +15 -0
  76. data/lib/decidim/admin/import/readers/json.rb +73 -3
  77. data/lib/decidim/admin/import/readers/xlsx.rb +25 -1
  78. data/lib/decidim/admin/import/readers.rb +7 -1
  79. data/lib/decidim/admin/import/verifier.rb +169 -0
  80. data/lib/decidim/admin/import.rb +3 -0
  81. data/lib/decidim/admin/test/filters_participatory_space_user_roles_examples.rb +165 -0
  82. data/lib/decidim/admin/test/manage_paginated_collection_examples.rb +8 -2
  83. data/lib/decidim/admin/test.rb +1 -0
  84. data/lib/decidim/admin/version.rb +1 -1
  85. metadata +19 -12
  86. data/app/packs/src/decidim/admin/import_guidance.js +0 -28
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 220c54b0fd0876978454350cb64cd37897c4f1342961bddafc005bdc3e645266
4
- data.tar.gz: f46dd18c9bc6cf05fb2498ea303e81cfc936babbd8fe3468ade4e597f5162699
3
+ metadata.gz: 6dd32d7d06cf46663a36708d5b0ee6a9cdf2ff4b2382c7c389222ea62e2ac765
4
+ data.tar.gz: ad9b4239d7ff4e76eae1f2ad68cc281016e117b14b5daa6f194d45a69fdda513
5
5
  SHA512:
6
- metadata.gz: ba849460b7a37a77d6c2730acece40c9390ea38664e80c94ad21a21e2162689bd48046d7c894de1432aa036a41c02d134c06f6e994b8a8adb00087c390ce2bce
7
- data.tar.gz: d96dbcb30cc913a978417111bf86ac7200310cc25e8244070b7c61ab59fd7d945428f87f8cd9c61d55d09e25578c80291cc0c1dcbffb92b8fff19c4b456eb8fe
6
+ metadata.gz: 0a4a0e4fd1e25a3ed486009740d5748ea3704f59ff537e5c6807a3f91d2b812a5fba16da051096083a41c0adf5d10949016a845cf0ff36c512d2367067d1e1c6
7
+ data.tar.gz: 7391b190aafcdd002353a4bacabd3d0020343c605e590772997fff861ec6a44e7cc7b6f18a8326122b43188922d4434b0bca15a77b49b2f9fcd4f06c25a2809e
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Admin
5
+ class CreateImportExample < Rectify::Command
6
+ def initialize(form)
7
+ @form = form
8
+ end
9
+
10
+ def call
11
+ return broadcast(:invalid) if form.invalid?
12
+
13
+ broadcast(:ok, form.example)
14
+ end
15
+
16
+ private
17
+
18
+ attr_reader :form
19
+ end
20
+ end
21
+ end
@@ -34,15 +34,21 @@ module Decidim
34
34
  @page = Decidim.traceability.create!(
35
35
  StaticPage,
36
36
  form.current_user,
37
+ attributes
38
+ )
39
+ end
40
+
41
+ def attributes
42
+ {
43
+ organization: form.organization,
37
44
  title: form.title,
38
45
  slug: form.slug,
39
- content: form.content,
40
46
  show_in_footer: form.show_in_footer,
41
47
  weight: form.weight,
42
48
  topic: form.topic,
43
- organization: form.organization,
49
+ content: form.content,
44
50
  allow_public_access: form.allow_public_access
45
- )
51
+ }
46
52
  end
47
53
 
48
54
  def update_organization_tos_version
@@ -102,7 +102,8 @@ module Decidim
102
102
  warning: form.warning_color,
103
103
  alert: form.alert_color,
104
104
  highlight: form.highlight_color,
105
- "highlight-alternative": form.highlight_alternative_color
105
+ "highlight-alternative": form.highlight_alternative_color,
106
+ theme: form.theme_color
106
107
  }
107
108
  }
108
109
  end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module Decidim
6
+ module Admin
7
+ module UserGroups
8
+ module Filterable
9
+ extend ActiveSupport::Concern
10
+
11
+ included do
12
+ include Decidim::Admin::Filterable
13
+
14
+ private
15
+
16
+ def base_query
17
+ collection
18
+ end
19
+
20
+ def search_field_predicate
21
+ :name_or_nickname_or_email_cont
22
+ end
23
+
24
+ def filters
25
+ [
26
+ :state_eq
27
+ ]
28
+ end
29
+
30
+ def filters_with_values
31
+ {
32
+ state_eq: user_groups_states
33
+ }
34
+ end
35
+
36
+ protected
37
+
38
+ def user_groups_states
39
+ %w(all pending rejected verified)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module Decidim
6
+ module ModeratedUsers
7
+ module Admin
8
+ module Filterable
9
+ extend ActiveSupport::Concern
10
+
11
+ included do
12
+ include Decidim::Admin::Filterable
13
+
14
+ private
15
+
16
+ def base_query
17
+ collection
18
+ end
19
+
20
+ def filters
21
+ [
22
+ :reports_reason_eq
23
+ ]
24
+ end
25
+
26
+ def filters_with_values
27
+ {
28
+ reports_reason_eq: report_reasons
29
+ }
30
+ end
31
+
32
+ def dynamically_translated_filters
33
+ []
34
+ end
35
+
36
+ def search_field_predicate
37
+ :user_name_or_user_nickname_or_user_email_cont
38
+ end
39
+
40
+ def report_reasons
41
+ Decidim::UserReport::REASONS
42
+ end
43
+
44
+ def extra_allowed_params
45
+ [:per_page, :blocked]
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -5,24 +5,24 @@ module Decidim
5
5
  # This controller allows admins to import resources from a file.
6
6
  class ImportsController < Decidim::Admin::ApplicationController
7
7
  include Decidim::ComponentPathHelper
8
- helper UserGroupHelper
8
+
9
+ helper_method :import_manifest
9
10
 
10
11
  def new
11
12
  enforce_permission_to :import, :component_data, component: current_component
12
- @form = form(Admin::ImportForm).from_params(
13
- {
14
- # We need to set "default" creator because form-class doesn't have context / current_component
15
- # when it sets it's default values.
16
- creator: current_component.manifest.import_manifests.first.creator
17
- },
13
+ raise ActionController::RoutingError, "Not Found" unless import_manifest
14
+
15
+ @form = form(import_manifest.form_class).from_params(
16
+ { name: import_manifest.name },
18
17
  current_component: current_component
19
18
  )
20
19
  end
21
20
 
22
21
  def create
23
22
  enforce_permission_to :import, :component_data, component: current_component
23
+ raise ActionController::RoutingError, "Not Found" unless import_manifest
24
24
 
25
- @form = form(Admin::ImportForm).from_params(
25
+ @form = form(import_manifest.form_class).from_params(
26
26
  params,
27
27
  current_component: current_component,
28
28
  current_organization: current_organization
@@ -31,8 +31,8 @@ module Decidim
31
31
  CreateImport.call(@form) do
32
32
  on(:ok) do |imported_data|
33
33
  flash[:notice] = t("decidim.admin.imports.notice",
34
- number: imported_data.length,
35
- resource_name: imported_data.first.resource_manifest.name.pluralize)
34
+ count: imported_data.length,
35
+ resource_name: import_manifest.message(:resource_name, count: imported_data.length))
36
36
  redirect_to manage_component_path(current_component)
37
37
  end
38
38
 
@@ -43,8 +43,46 @@ module Decidim
43
43
  end
44
44
  end
45
45
 
46
+ def example
47
+ enforce_permission_to :import, :component_data, component: current_component
48
+ raise ActionController::RoutingError, "Not Found" unless import_manifest
49
+
50
+ @form = form(Decidim::Admin::ImportExampleForm).from_params(params).with_context(
51
+ current_component: current_component,
52
+ current_organization: current_organization
53
+ )
54
+
55
+ respond_to do |format|
56
+ @form.available_formats.each do |key, mime|
57
+ format.public_send(key) do
58
+ CreateImportExample.call(@form) do
59
+ on(:ok) do |data|
60
+ filename = "#{current_component.manifest_name}-#{import_manifest.name}-example.#{key}"
61
+ send_data data.read, disposition: :attachment, filename: filename, type: mime
62
+ end
63
+
64
+ on(:invalid) do
65
+ flash[:alert] = t("decidim.admin.imports.example_error")
66
+ redirect_to admin_imports_path(current_component, name: import_name)
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+
46
74
  private
47
75
 
76
+ def import_manifest
77
+ @import_manifest ||= current_component.manifest.import_manifests.find do |import_manifest|
78
+ import_manifest.name.to_s == import_name
79
+ end
80
+ end
81
+
82
+ def import_name
83
+ params[:name]
84
+ end
85
+
48
86
  def current_component
49
87
  @current_component ||= current_participatory_space.components.find(params[:component_id])
50
88
  end
@@ -3,14 +3,14 @@
3
3
  module Decidim
4
4
  module Admin
5
5
  class ModeratedUsersController < Decidim::Admin::ApplicationController
6
- include Decidim::Moderations::Admin::Filterable
6
+ include Decidim::ModeratedUsers::Admin::Filterable
7
7
 
8
8
  layout "decidim/admin/users"
9
9
 
10
10
  def index
11
11
  enforce_permission_to :read, :moderate_users
12
12
 
13
- @moderated_users = filtered_collection.page(params[:page]).per(15)
13
+ @moderated_users = filtered_collection
14
14
  end
15
15
 
16
16
  def ignore
@@ -10,7 +10,8 @@ module Decidim
10
10
 
11
11
  def index
12
12
  enforce_permission_to :read, :scope
13
- @scopes = children_scopes.order(Arel.sql("name->'#{I18n.locale}' ASC"))
13
+ field = Arel::Nodes::InfixOperation.new("->", Decidim::Scope.arel_table[:name], Arel::Nodes.build_quoted(I18n.locale))
14
+ @scopes = children_scopes.order(Arel::Nodes::InfixOperation.new("", field, Arel.sql("ASC")))
14
15
  end
15
16
 
16
17
  def new
@@ -6,6 +6,7 @@ module Decidim
6
6
  #
7
7
  class UserGroupsController < Decidim::Admin::ApplicationController
8
8
  include UserGroups
9
+ include Decidim::Admin::UserGroups::Filterable
9
10
 
10
11
  before_action :enforce_user_groups_enabled
11
12
 
@@ -13,11 +14,8 @@ module Decidim
13
14
 
14
15
  def index
15
16
  enforce_permission_to :index, :user_group
16
- @query = params[:q]
17
- @state = params[:state]
18
17
 
19
- @user_groups = Decidim::Admin::UserGroupsEvaluation.for(collection, @query, @state)
20
- .page(params[:page]).per(15)
18
+ @user_groups = filtered_collection
21
19
  end
22
20
 
23
21
  def verify
@@ -56,10 +54,20 @@ module Decidim
56
54
 
57
55
  private
58
56
 
57
+ def filtered_collection
58
+ paginate(query.result)
59
+ end
60
+
61
+ def base_query
62
+ Decidim::Admin::UserGroupsEvaluation.for(collection, @query, @state)
63
+ end
64
+
59
65
  def collection
60
66
  UserGroup
61
- .includes(:memberships)
67
+ .left_outer_joins(:memberships)
68
+ .select("decidim_users.*, COUNT(decidim_user_group_memberships.decidim_user_group_id) as users_count")
62
69
  .where(decidim_user_group_memberships: { decidim_user_id: current_organization.users })
70
+ .group(Arel.sql("decidim_users.id"))
63
71
  end
64
72
  end
65
73
  end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Admin
5
+ class ImportExampleForm < Form
6
+ attribute :name, String
7
+ attribute :format, String
8
+
9
+ validates :name, presence: true
10
+ validates :format, presence: true
11
+ validates :manifest, presence: true
12
+ validates :reader_klass, presence: true
13
+ validates :example_data, presence: true
14
+
15
+ def example
16
+ reader.example_file(example_data)
17
+ end
18
+
19
+ def available_formats
20
+ Decidim::Admin::Import::Readers::ACCEPTED_MIME_TYPES
21
+ end
22
+
23
+ private
24
+
25
+ def manifest
26
+ @manifest ||= current_component.manifest.import_manifests.find do |import_manifest|
27
+ import_manifest.name.to_s == name
28
+ end
29
+ end
30
+
31
+ def example_data
32
+ return unless manifest
33
+
34
+ manifest.example(self, current_component)
35
+ end
36
+
37
+ def reader
38
+ @reader ||= begin
39
+ return unless reader_klass
40
+
41
+ reader_klass.new("/dev/null")
42
+ end
43
+ end
44
+
45
+ def reader_klass
46
+ @reader_klass ||= Decidim::Admin::Import::Readers.search_by_file_extension(format)
47
+ end
48
+ end
49
+ end
50
+ end
@@ -6,36 +6,23 @@ module Decidim
6
6
  ACCEPTED_MIME_TYPES = Decidim::Admin::Import::Readers::ACCEPTED_MIME_TYPES
7
7
  include Decidim::HasUploadValidations
8
8
 
9
- attribute :creator, String, default: ->(form, _attribute) { form.creators.first[:creator].to_s }
9
+ attribute :name, String
10
10
  attribute :file
11
- attribute :user_group_id, Integer
12
11
 
13
12
  validates :file, presence: true
14
- validates :creator, presence: true
15
- validate :accepted_mime_type
16
- validate :check_invalid_lines
13
+ validates :name, presence: true
14
+ validate :check_accepted_mime_type
15
+ validate :check_invalid_file, if: -> { file.present? && accepted_mime_type? }
16
+ validate :verify_import, if: -> { file.present? && accepted_mime_type? && !importer.invalid_file? }
17
17
 
18
- def check_invalid_lines
19
- return if file.blank? || !accepted_mime_type
20
-
21
- importer.prepare
22
- invalid_lines = importer.invalid_lines
23
- errors.add(:file, I18n.t("decidim.admin.imports.invalid_lines", invalid_lines: invalid_lines.join(","))) unless invalid_lines.empty?
24
- end
25
-
26
- def file_path
27
- file&.path
18
+ def importer
19
+ @importer ||= importer_for(file_path, mime_type)
28
20
  end
29
21
 
30
- def mime_type
31
- file&.content_type
32
- end
22
+ private
33
23
 
34
- def accepted_mime_type
35
- accepted_mime_types = ACCEPTED_MIME_TYPES.values
36
- return true if accepted_mime_types.include?(mime_type)
37
- # Avoid duplicating error messages
38
- return false if errors[:file].present?
24
+ def check_accepted_mime_type
25
+ return if accepted_mime_type?
39
26
 
40
27
  errors.add(
41
28
  :file,
@@ -46,41 +33,60 @@ module Decidim
46
33
  end.join(", ")
47
34
  )
48
35
  )
49
- false
50
36
  end
51
37
 
52
- def creators
53
- @creators ||= current_component.manifest.import_manifests.map do |manifest|
54
- { creator: manifest.creator, name: manifest.creator.to_s.split("::").last.downcase }
55
- end
38
+ def check_invalid_file
39
+ return unless importer.invalid_file?
40
+
41
+ errors.add(:file, I18n.t("activemodel.errors.new_import.attributes.file.invalid_file"))
56
42
  end
57
43
 
58
- def creator_class
59
- return creator.constantize if creator.is_a?(String)
44
+ def verify_import
45
+ return if importer.verify
60
46
 
61
- creator
47
+ importer.errors.each do |_col, message|
48
+ errors.add(:file, message)
49
+ end
62
50
  end
63
51
 
64
- def user_group
65
- @user_group ||= Decidim::UserGroup.find_by(
66
- organization: current_organization,
67
- id: user_group_id.to_i
68
- )
52
+ def file_path
53
+ file&.path
69
54
  end
70
55
 
71
- def importer
72
- @importer ||= importer_for(file_path, mime_type)
56
+ def mime_type
57
+ file&.content_type
58
+ end
59
+
60
+ def creator_class
61
+ manifest.creator
73
62
  end
74
63
 
75
64
  def importer_for(filepath, mime_type)
76
- context[:user_group] = user_group
77
65
  Import::ImporterFactory.build(
78
66
  filepath,
79
67
  mime_type,
80
- context: context,
68
+ context: importer_context,
81
69
  creator: creator_class
82
70
  )
83
71
  end
72
+
73
+ protected
74
+
75
+ def accepted_mime_type?
76
+ return true if ACCEPTED_MIME_TYPES.values.include?(mime_type)
77
+
78
+ false
79
+ end
80
+
81
+ def importer_context
82
+ context
83
+ end
84
+
85
+ def manifest
86
+ @manifest ||= current_component.manifest.import_manifests.find do |import_manifest|
87
+ import_manifest.name.to_s == name
88
+ end
89
+ end
84
90
  end
85
91
  end
86
92
  end
@@ -36,6 +36,7 @@ module Decidim
36
36
  attribute :alert_color, String, default: "#ec5840"
37
37
  attribute :highlight_color, String, default: "#be6400"
38
38
  attribute :highlight_alternative_color, String, default: "#ff5731"
39
+ attribute :theme_color, String, default: "#ef604d"
39
40
 
40
41
  translatable_attribute :cta_button_text, String
41
42
  translatable_attribute :description, String
@@ -12,13 +12,13 @@ module Decidim
12
12
  # resource_id - The resource id that is passed to route.
13
13
  #
14
14
  # Returns a rendered dropdown.
15
- def import_dropdown(component = current_component, resource_id = nil)
16
- locals = { component: component, resource_id: resource_id }
17
- locals[:block] = yield if block_given?
18
- render partial: "decidim/admin/imports/dropdown", locals: locals
15
+ def import_dropdown(component = current_component, resource_id: nil)
16
+ render "decidim/admin/imports/dropdown", component: component, resource_id: resource_id, custom: block_given? do
17
+ yield if block_given?
18
+ end
19
19
  end
20
20
 
21
- # Routes to the correct importer for a component.
21
+ # Route to the correct importer for a component.
22
22
  #
23
23
  # component - The component to be routed.
24
24
  # options - Extra options that need to be passed to the route.
@@ -28,10 +28,20 @@ module Decidim
28
28
  EngineRouter.admin_proxy(component.participatory_space).new_component_import_path(options.merge(component_id: component))
29
29
  end
30
30
 
31
+ # Route to the correct importer example for a component.
32
+ #
33
+ # component - The component to be routed.
34
+ # options - Extra options that need to be passed to the route.
35
+ #
36
+ # Returns the path to the component importer example.
37
+ def admin_imports_example_path(component, options)
38
+ EngineRouter.admin_proxy(component.participatory_space).example_component_imports_path(options.merge(component_id: component))
39
+ end
40
+
31
41
  # Public: A formatted collection of mime_type to be used in forms.
32
42
  def mime_types
33
43
  accepted_mime_types = Decidim::Admin::Import::Readers::ACCEPTED_MIME_TYPES.keys
34
- accepted_mime_types.map { |mime_type| t("decidim.admin.imports.new.accepted_mime_types.#{mime_type}") }.join(", ")
44
+ accepted_mime_types.index_with { |mime_type| I18n.t("decidim.admin.imports.new.accepted_mime_types.#{mime_type}") }
35
45
  end
36
46
 
37
47
  # Returns verified user groups of current user
@@ -29,6 +29,15 @@ module Decidim
29
29
  content_tag(:td, scope_name)
30
30
  end
31
31
 
32
+ # Public: This helper shows th with the sort link element.
33
+ def th_scope_sort_link
34
+ return unless resource_with_scopes_enabled?
35
+
36
+ content_tag(:th) do
37
+ sort_link(query, :scope_name, t("decidim.admin.resources.index.headers.scope"))
38
+ end
39
+ end
40
+
32
41
  private
33
42
 
34
43
  def resource_with_scopes_enabled?
@@ -12,6 +12,7 @@ module Decidim
12
12
  integer: :number_field,
13
13
  string: :text_field,
14
14
  text: :text_area,
15
+ select: :select_field,
15
16
  scope: :scope_field,
16
17
  enum: :collection_radio_buttons,
17
18
  time: :datetime_field
@@ -49,6 +50,8 @@ module Decidim
49
50
  form.send(:translated, form_method, name, options)
50
51
  elsif form_method == :collection_radio_buttons
51
52
  render_enum_form_field(form, attribute, name, i18n_scope, options)
53
+ elsif form_method == :select_field
54
+ render_select_form_field(form, attribute, name, i18n_scope, options)
52
55
  elsif form_method == :scope_field
53
56
  scopes_picker_field(form, name)
54
57
  else
@@ -59,6 +62,16 @@ module Decidim
59
62
 
60
63
  private
61
64
 
65
+ def render_select_form_field(form, attribute, name, i18n_scope, options)
66
+ html = form.select(
67
+ name,
68
+ attribute.build_choices.map { |o| [t("#{name}_options.#{o}", scope: i18n_scope), o] },
69
+ { include_blank: attribute.include_blank, label: options[:label] }
70
+ )
71
+ html << content_tag(:p, options[:help_text], class: "help-text") if options[:help_text]
72
+ html
73
+ end
74
+
62
75
  # Returns a radio buttons collection input for the given attribute
63
76
  def render_enum_form_field(form, attribute, name, i18n_scope, options)
64
77
  html = label_tag(name) do
@@ -20,7 +20,6 @@ import "src/decidim/admin/resources_permissions"
20
20
  import "src/decidim/admin/welcome_notification"
21
21
  import "src/decidim/admin/newsletters"
22
22
  import "src/decidim/admin/form"
23
- import "src/decidim/admin/import_guidance"
24
23
  import "src/decidim/admin/external_domain_whitelist"
25
24
  import "src/decidim/confirm"
26
25
  import "src/decidim/admin/draggable-list"
@@ -6,8 +6,10 @@ class DynamicFieldsComponent {
6
6
  this.fieldSelector = options.fieldSelector;
7
7
  this.addFieldButtonSelector = options.addFieldButtonSelector;
8
8
  this.addSeparatorButtonSelector = options.addSeparatorButtonSelector;
9
+ this.addTitleAndDescriptionButtonSelector = options.addTitleAndDescriptionButtonSelector;
9
10
  this.fieldTemplateSelector = options.fieldTemplateSelector;
10
11
  this.separatorTemplateSelector = options.separatorTemplateSelector;
12
+ this.TitleAndDescriptionTemplateSelector = options.TitleAndDescriptionTemplateSelector;
11
13
  this.removeFieldButtonSelector = options.removeFieldButtonSelector;
12
14
  this.moveUpFieldButtonSelector = options.moveUpFieldButtonSelector;
13
15
  this.moveDownFieldButtonSelector = options.moveDownFieldButtonSelector;
@@ -84,6 +86,12 @@ class DynamicFieldsComponent {
84
86
  );
85
87
  }
86
88
 
89
+ if (this.addTitleAndDescriptionButtonSelector) {
90
+ $(this.wrapperSelector).on("click", this.addTitleAndDescriptionButtonSelector, (event) =>
91
+ this._bindSafeEvent(event, () => this._addField(this.TitleAndDescriptionTemplateSelector))
92
+ );
93
+ }
94
+
87
95
  $(this.wrapperSelector).on("click", this.removeFieldButtonSelector, (event) =>
88
96
  this._bindSafeEvent(event, (target) => this._removeField(target))
89
97
  );
@@ -42,6 +42,7 @@ module Decidim
42
42
  allow! if permission_action.subject == :component
43
43
  allow! if permission_action.subject == :admin_user
44
44
  allow! if permission_action.subject == :attachment
45
+ allow! if permission_action.subject == :editor_image
45
46
  allow! if permission_action.subject == :attachment_collection
46
47
  allow! if permission_action.subject == :scope
47
48
  allow! if permission_action.subject == :scope_type
@@ -1,9 +1,14 @@
1
1
  <span class="imports dropdown tiny button button--simple" data-toggle="import-dropdown"><%= t "actions.import", scope: "decidim.admin" %></span>
2
2
  <div class="dropdown-pane" id="import-dropdown" data-dropdown data-position=bottom data-alignment=right data-auto-focus="true" data-close-on-click="true">
3
3
  <ul class="vertical menu add-components">
4
- <%= block if defined?(block) %>
5
- <li class="imports--file imports--<%= component.manifest.name %>">
6
- <%= link_to t("decidim.admin.imports.import_from_file"), admin_imports_path(component, resource_id: resource_id) %>
7
- </li>
4
+ <% if custom %>
5
+ <%= yield %>
6
+ <% else %>
7
+ <% component.manifest.import_manifests.each do |import_manifest| %>
8
+ <li class="imports--file imports--<%= import_manifest.name %>">
9
+ <%= link_to import_manifest.message(:label, self), admin_imports_path(component, resource_id: resource_id, name: import_manifest.name) %>
10
+ </li>
11
+ <% end %>
12
+ <% end %>
8
13
  </ul>
9
14
  </div>