decidim-admin 0.23.1 → 0.24.0.rc2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of decidim-admin might be problematic. Click here for more details.

Files changed (184) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/decidim_admin_manifest.js +1 -0
  3. data/app/assets/javascripts/decidim/admin/application.js.es6 +2 -0
  4. data/app/assets/javascripts/decidim/admin/budget_rule_toggler.component.js.es6 +23 -20
  5. data/app/assets/javascripts/decidim/admin/bundle.js +10 -17
  6. data/app/assets/javascripts/decidim/admin/bundle.js.map +1 -1
  7. data/app/assets/javascripts/decidim/admin/form.js.es6 +1 -0
  8. data/app/assets/javascripts/decidim/admin/import_guidance.js.es6 +29 -0
  9. data/app/assets/javascripts/decidim/admin/moderations.js.es6 +24 -0
  10. data/app/assets/javascripts/decidim/admin/proposal_infinite_edit.js.es6 +20 -0
  11. data/app/assets/javascripts/decidim/admin/subform_multi_toggler.component.js.es6 +2 -2
  12. data/app/assets/javascripts/decidim/admin/subform_toggler.component.js.es6 +2 -2
  13. data/app/assets/javascripts/decidim/admin/user_moderations.js +2 -0
  14. data/app/assets/stylesheets/decidim/admin/_variables.scss +9 -0
  15. data/app/assets/stylesheets/decidim/admin/components/_dropdown-menu.scss +3 -0
  16. data/app/assets/stylesheets/decidim/admin/extra/_action-icon.scss +13 -0
  17. data/app/assets/stylesheets/decidim/admin/extra/_block_user.scss +5 -0
  18. data/app/assets/stylesheets/decidim/admin/extra/_title_bar.scss +1 -0
  19. data/app/assets/stylesheets/decidim/admin/modules/_buttons.scss +1 -0
  20. data/app/assets/stylesheets/decidim/admin/modules/_moderations.scss +39 -0
  21. data/app/assets/stylesheets/decidim/admin/modules/_modules.scss +2 -0
  22. data/app/assets/stylesheets/decidim/admin/modules/_reveal.scss +5 -0
  23. data/app/assets/stylesheets/decidim/admin/modules/_secondary-nav.scss +6 -3
  24. data/app/assets/stylesheets/decidim/admin/modules/_user-login.scss +2 -2
  25. data/app/assets/stylesheets/decidim/admin/user_moderations.scss +3 -0
  26. data/app/assets/stylesheets/decidim/admin/utils/_settings.scss +1 -0
  27. data/app/cells/decidim/admin/content_block/show.erb +1 -1
  28. data/app/cells/decidim/admin/content_block_cell.rb +4 -0
  29. data/app/commands/decidim/admin/block_user.rb +70 -0
  30. data/app/commands/decidim/admin/create_import.rb +29 -0
  31. data/app/commands/decidim/admin/create_participatory_space_admin_user_actions.rb +98 -0
  32. data/app/commands/decidim/admin/create_participatory_space_private_user.rb +1 -1
  33. data/app/commands/decidim/admin/create_static_page.rb +2 -1
  34. data/app/commands/decidim/admin/hide_resource.rb +21 -0
  35. data/app/commands/decidim/admin/impersonate_user.rb +17 -1
  36. data/app/commands/decidim/admin/promote_managed_user.rb +10 -0
  37. data/app/commands/decidim/admin/reorder_content_blocks.rb +6 -3
  38. data/app/commands/decidim/admin/transfer_user.rb +78 -0
  39. data/app/commands/decidim/admin/unblock_user.rb +48 -0
  40. data/app/commands/decidim/admin/unreport_user.rb +46 -0
  41. data/app/commands/decidim/admin/update_organization_appearance.rb +12 -4
  42. data/app/commands/decidim/admin/update_static_page.rb +2 -1
  43. data/app/commands/decidim/admin/verify_user_group.rb +1 -1
  44. data/app/controllers/concerns/decidim/admin/filterable.rb +1 -1
  45. data/app/controllers/concerns/decidim/admin/global_moderation_context.rb +51 -0
  46. data/app/controllers/concerns/decidim/admin/landing_page.rb +105 -0
  47. data/app/controllers/concerns/decidim/admin/landing_page_content_blocks.rb +118 -0
  48. data/app/controllers/concerns/decidim/moderations/admin/filterable.rb +54 -0
  49. data/app/controllers/decidim/admin/block_user_controller.rb +60 -0
  50. data/app/controllers/decidim/admin/components/base_controller.rb +1 -0
  51. data/app/controllers/decidim/admin/conflicts_controller.rb +46 -0
  52. data/app/controllers/decidim/admin/exports_controller.rb +1 -2
  53. data/app/controllers/decidim/admin/global_moderations/reports_controller.rb +18 -0
  54. data/app/controllers/decidim/admin/global_moderations_controller.rb +32 -0
  55. data/app/controllers/decidim/admin/impersonations_controller.rb +1 -1
  56. data/app/controllers/decidim/admin/imports_controller.rb +52 -0
  57. data/app/controllers/decidim/admin/moderated_users_controller.rb +44 -0
  58. data/app/controllers/decidim/admin/moderations/reports_controller.rb +39 -0
  59. data/app/controllers/decidim/admin/moderations_controller.rb +31 -7
  60. data/app/controllers/decidim/admin/officializations_controller.rb +3 -3
  61. data/app/controllers/decidim/admin/organization_homepage_controller.rb +6 -2
  62. data/app/controllers/decidim/admin/static_pages_controller.rb +7 -0
  63. data/app/events/decidim/resource_hidden_event.rb +37 -0
  64. data/app/forms/decidim/admin/block_user_form.rb +25 -0
  65. data/app/forms/decidim/admin/import_form.rb +85 -0
  66. data/app/forms/decidim/admin/organization_appearance_form.rb +1 -2
  67. data/app/forms/decidim/admin/participatory_space_private_user_csv_import_form.rb +4 -5
  68. data/app/forms/decidim/admin/participatory_space_private_user_form.rb +0 -5
  69. data/app/forms/decidim/admin/selective_newsletter_form.rb +6 -0
  70. data/app/forms/decidim/admin/static_page_form.rb +6 -1
  71. data/app/forms/decidim/admin/transfer_user_form.rb +19 -0
  72. data/app/helpers/decidim/admin/admin_terms_helper.rb +0 -7
  73. data/app/helpers/decidim/admin/application_helper.rb +5 -4
  74. data/app/helpers/decidim/admin/exports_helper.rb +2 -2
  75. data/app/helpers/decidim/admin/filterable_helper.rb +3 -2
  76. data/app/helpers/decidim/admin/imports_helper.rb +43 -0
  77. data/app/helpers/decidim/admin/menu_helper.rb +10 -0
  78. data/app/helpers/decidim/admin/moderations/reports_helper.rb +40 -0
  79. data/app/helpers/decidim/admin/moderations_helper.rb +36 -0
  80. data/app/helpers/decidim/admin/newsletters_helper.rb +4 -10
  81. data/app/helpers/decidim/admin/settings_helper.rb +2 -1
  82. data/app/helpers/decidim/admin/sidebar_menu_helper.rb +13 -0
  83. data/app/helpers/decidim/admin/user_moderations_helper.rb +6 -0
  84. data/app/jobs/decidim/admin/import_participatory_space_private_user_csv_job.rb +1 -1
  85. data/app/jobs/decidim/admin/verify_user_group_from_csv_job.rb +1 -1
  86. data/app/permissions/decidim/admin/permissions.rb +7 -6
  87. data/app/presenters/decidim/admin/dashboard_metric_charts_presenter.rb +1 -1
  88. data/app/presenters/decidim/admin/secondary_menu_presenter.rb +26 -0
  89. data/app/queries/decidim/admin/active_users_counter.rb +1 -2
  90. data/app/queries/decidim/admin/newsletter_recipients.rb +0 -7
  91. data/app/queries/decidim/admin/user_filter.rb +1 -2
  92. data/app/views/decidim/admin/admin_terms/show.html.erb +1 -1
  93. data/app/views/decidim/admin/attachment_collections/index.html.erb +1 -1
  94. data/app/views/decidim/admin/attachments/index.html.erb +1 -1
  95. data/app/views/decidim/admin/block_user/new.html.erb +22 -0
  96. data/app/views/decidim/admin/categories/index.html.erb +1 -1
  97. data/app/views/decidim/admin/components/_component.html.erb +12 -0
  98. data/app/views/decidim/admin/components/_form.html.erb +1 -1
  99. data/app/views/decidim/admin/conflicts/edit.html.erb +46 -0
  100. data/app/views/decidim/admin/conflicts/index.html.erb +34 -0
  101. data/app/views/decidim/admin/dashboard/show.html.erb +2 -1
  102. data/app/views/decidim/admin/exports/_dropdown.html.erb +1 -1
  103. data/app/views/decidim/admin/imports/_dropdown.html.erb +9 -0
  104. data/app/views/decidim/admin/imports/new.html.erb +57 -0
  105. data/app/views/decidim/admin/moderated_users/_report.html.erb +10 -0
  106. data/app/views/decidim/admin/moderated_users/index.html.erb +78 -0
  107. data/app/views/decidim/admin/moderations/_report.html.erb +1 -1
  108. data/app/views/decidim/admin/moderations/index.html.erb +27 -9
  109. data/app/views/decidim/admin/moderations/reports/index.html.erb +102 -0
  110. data/app/views/decidim/admin/moderations/reports/show.html.erb +62 -0
  111. data/app/views/decidim/admin/newsletters/index.html.erb +1 -1
  112. data/app/views/decidim/admin/newsletters/select_recipients_to_deliver.html.erb +2 -2
  113. data/app/views/decidim/admin/officializations/index.html.erb +13 -4
  114. data/app/views/decidim/admin/organization_appearance/_form.html.erb +0 -4
  115. data/app/views/decidim/admin/organization_appearance/form/_colors.html.erb +1 -1
  116. data/app/views/decidim/admin/organization_appearance/form/_images.html.erb +4 -4
  117. data/app/views/decidim/admin/participatory_space_private_users/index.html.erb +1 -1
  118. data/app/views/decidim/admin/shared/_gallery.html.erb +1 -1
  119. data/app/views/decidim/admin/shared/landing_page/edit.html.erb +47 -0
  120. data/app/views/decidim/admin/shared/landing_page_content_blocks/edit.html.erb +15 -0
  121. data/app/views/decidim/admin/static_pages/_form.html.erb +6 -0
  122. data/app/views/decidim/admin/users/index.html.erb +1 -1
  123. data/app/views/layouts/decidim/admin/_application.html.erb +5 -1
  124. data/app/views/layouts/decidim/admin/_title_bar.html.erb +2 -2
  125. data/app/views/layouts/decidim/admin/global_moderations.html.erb +7 -0
  126. data/app/views/layouts/decidim/admin/newsletters.erb +1 -1
  127. data/app/views/layouts/decidim/admin/settings.html.erb +2 -33
  128. data/app/views/layouts/decidim/admin/users.html.erb +11 -0
  129. data/config/locales/ar.yml +0 -9
  130. data/config/locales/bg.yml +0 -5
  131. data/config/locales/ca.yml +151 -8
  132. data/config/locales/cs.yml +194 -51
  133. data/config/locales/de.yml +172 -28
  134. data/config/locales/el.yml +62 -9
  135. data/config/locales/en.yml +152 -9
  136. data/config/locales/es-MX.yml +150 -7
  137. data/config/locales/es-PY.yml +150 -7
  138. data/config/locales/es.yml +150 -7
  139. data/config/locales/eu.yml +18 -21
  140. data/config/locales/fi-plain.yml +150 -7
  141. data/config/locales/fi.yml +150 -7
  142. data/config/locales/fr-CA.yml +141 -8
  143. data/config/locales/fr.yml +142 -9
  144. data/config/locales/gl.yml +225 -4
  145. data/config/locales/hu.yml +13 -9
  146. data/config/locales/id-ID.yml +0 -3
  147. data/config/locales/is-IS.yml +36 -6
  148. data/config/locales/it.yml +74 -9
  149. data/config/locales/ja.yml +43 -12
  150. data/config/locales/lv.yml +0 -9
  151. data/config/locales/nl.yml +120 -11
  152. data/config/locales/no.yml +16 -9
  153. data/config/locales/pl.yml +168 -24
  154. data/config/locales/pt-BR.yml +0 -3
  155. data/config/locales/pt.yml +0 -9
  156. data/config/locales/ro-RO.yml +21 -9
  157. data/config/locales/ru.yml +0 -7
  158. data/config/locales/si-LK.yml +1 -0
  159. data/config/locales/sk.yml +0 -9
  160. data/config/locales/sl.yml +0 -5
  161. data/config/locales/sr-CS.yml +0 -7
  162. data/config/locales/sv.yml +53 -9
  163. data/config/locales/sw-KE.yml +1 -0
  164. data/config/locales/tr-TR.yml +206 -11
  165. data/config/locales/uk.yml +0 -3
  166. data/config/locales/zh-CN.yml +0 -9
  167. data/config/routes.rb +21 -1
  168. data/lib/decidim/admin.rb +6 -0
  169. data/lib/decidim/admin/engine.rb +76 -1
  170. data/lib/decidim/admin/import.rb +12 -0
  171. data/lib/decidim/admin/import/creator.rb +82 -0
  172. data/lib/decidim/admin/import/importer.rb +82 -0
  173. data/lib/decidim/admin/import/importer_factory.rb +17 -0
  174. data/lib/decidim/admin/import/readers.rb +39 -0
  175. data/lib/decidim/admin/import/readers/base.rb +31 -0
  176. data/lib/decidim/admin/import/readers/csv.rb +23 -0
  177. data/lib/decidim/admin/import/readers/json.rb +25 -0
  178. data/lib/decidim/admin/import/readers/xls.rb +25 -0
  179. data/lib/decidim/admin/test/commands/create_attachment_collection_examples.rb +6 -6
  180. data/lib/decidim/admin/test/commands/create_category_examples.rb +6 -6
  181. data/lib/decidim/admin/test/filterable_examples.rb +1 -8
  182. data/lib/decidim/admin/test/manage_moderations_examples.rb +49 -4
  183. data/lib/decidim/admin/version.rb +1 -1
  184. metadata +78 -19
@@ -55,7 +55,6 @@ uk:
55
55
  omnipresent_banner_title: Заголовок
56
56
  omnipresent_banner_url: Веб-адреса
57
57
  reference_prefix: Довідковий префікс
58
- show_statistics: Показувати статистику
59
58
  tos_version: Версія умов участі
60
59
  twitter_handler: Адреса Twitter
61
60
  youtube_handler: Адреса YouTube
@@ -440,7 +439,6 @@ uk:
440
439
  instagram: Інстаграм
441
440
  social_handlers: Соціальні мережі
442
441
  twitter: Твіттер
443
- url: Веб-адреса
444
442
  youtube: ЮТуб
445
443
  update:
446
444
  error: При спробі оновити цю організацію сталася помилка.
@@ -598,7 +596,6 @@ uk:
598
596
  fields:
599
597
  hidden_at: 'Приховано:'
600
598
  report_count: Кількість
601
- reportable: Різновид скарги
602
599
  reported_content_url: Веб-адреса оскарженого вмісту
603
600
  reports: Скарги
604
601
  visit_url: Відвідайте веб-адресу
@@ -30,7 +30,6 @@ zh-CN:
30
30
  body: 正文内容
31
31
  subject: 议 题
32
32
  organization:
33
- address: SMTP hostname
34
33
  alert_color: 警告
35
34
  badges_enabled: 启用徽章
36
35
  comments_max_length: 评论最大长度 (默认值留0)
@@ -66,20 +65,16 @@ zh-CN:
66
65
  omnipresent_banner_short_description: 简短描述
67
66
  omnipresent_banner_title: 标题
68
67
  omnipresent_banner_url: 网址
69
- password: 密码
70
- port: 端口
71
68
  primary_color: 主要的
72
69
  reference_prefix: 参考前缀
73
70
  rich_text_editor_in_public_views: 为参与者启用富文本编辑器
74
71
  secondary_color: 次要文件
75
72
  send_welcome_notification: 发送欢迎通知
76
- show_statistics: 显示统计
77
73
  success_color: 成功
78
74
  time_zone: 时区
79
75
  tos_version: 服务条款版本
80
76
  twitter_handler: Twitter handler
81
77
  user_groups_enabled: 启用组
82
- user_name: 用户名
83
78
  warning_color: 警告
84
79
  welcome_notification_body: 欢迎通知机构
85
80
  welcome_notification_subject: 欢迎通知主题
@@ -150,7 +145,6 @@ zh-CN:
150
145
  error: 接受管理员使用条款时出错。
151
146
  success: 太棒了!您已经接受了管理员使用条款。
152
147
  actions:
153
- accept: 我同意这个管理条款
154
148
  are_you_sure: 您确定要拒绝管理员条款吗?
155
149
  refuse: 拒绝管理条款
156
150
  title: 同意使用条款
@@ -586,7 +580,6 @@ zh-CN:
586
580
  rich_text_editor_in_public_views_help: 在某些文本领域,参与者将能够通过使用丰富的文本编辑器插入一些HTML标签。
587
581
  social_handlers: 社交活动
588
582
  twitter: 推特
589
- url: 网址
590
583
  youtube: YouTube
591
584
  update:
592
585
  error: 更新这个组织时出现问题。
@@ -621,7 +614,6 @@ zh-CN:
621
614
  error: 删除这个参与空间的私人参与者时出错。
622
615
  success: 参与性空间私人参与者访问成功被摧毁。
623
616
  index:
624
- import_via_csv: 通过 csv 导入
625
617
  title: 参与性空间私人参与者
626
618
  new:
627
619
  create: 创建
@@ -831,7 +823,6 @@ zh-CN:
831
823
  fields:
832
824
  hidden_at: 隐藏于
833
825
  report_count: 计数
834
- reportable: 可重写
835
826
  reported_content_url: 报告的内容 URL
836
827
  reports: 报告
837
828
  visit_url: 访问 URL
data/config/routes.rb CHANGED
@@ -38,10 +38,19 @@ Decidim::Admin::Engine.routes.draw do
38
38
  member do
39
39
  post :resend_invitation, to: "users#resend_invitation"
40
40
  end
41
+ resource :block, only: [:new, :create, :destroy], controller: :block_user
41
42
  end
42
43
 
43
44
  resources :officializations, only: [:new, :create, :index, :destroy], param: :user_id do
44
- get :show_email, on: :member
45
+ member do
46
+ get :show_email
47
+ end
48
+ end
49
+
50
+ resources :moderated_users, only: [:index] do
51
+ member do
52
+ put :ignore
53
+ end
45
54
  end
46
55
 
47
56
  resources :impersonatable_users, only: [:index] do
@@ -90,6 +99,17 @@ Decidim::Admin::Engine.routes.draw do
90
99
 
91
100
  resources :share_tokens, only: :destroy
92
101
 
102
+ resources :moderations, controller: "global_moderations" do
103
+ member do
104
+ put :unreport
105
+ put :hide
106
+ put :unhide
107
+ end
108
+ resources :reports, controller: "global_moderations/reports", only: [:index, :show]
109
+ end
110
+
111
+ resources :conflicts, only: [:index, :edit, :update], controller: "conflicts"
112
+
93
113
  root to: "dashboard#show"
94
114
  end
95
115
  end
data/lib/decidim/admin.rb CHANGED
@@ -11,6 +11,7 @@ module Decidim
11
11
  module Admin
12
12
  autoload :Components, "decidim/admin/components"
13
13
  autoload :FormBuilder, "decidim/admin/form_builder"
14
+ autoload :Import, "decidim/admin/import"
14
15
 
15
16
  include ActiveSupport::Configurable
16
17
 
@@ -28,5 +29,10 @@ module Decidim
28
29
  config.default_per_page = Decidim::Admin.per_page_range.first
29
30
  config.max_per_page = Decidim::Admin.per_page_range.last
30
31
  end
32
+
33
+ # Public: Stores an instance of ViewHooks
34
+ def self.view_hooks
35
+ @view_hooks ||= ViewHooks.new
36
+ end
31
37
  end
32
38
  end
@@ -32,6 +32,70 @@ module Decidim
32
32
  app.config.assets.precompile += %w(decidim_admin_manifest.js)
33
33
  end
34
34
 
35
+ initializer "decidim_admin.global_moderation_menu" do
36
+ Decidim.menu :admin_global_moderation_menu do |menu|
37
+ menu.item I18n.t("actions.not_hidden", scope: "decidim.moderations"),
38
+ decidim_admin.moderations_path,
39
+ position: 1,
40
+ active: params[:hidden].blank?
41
+
42
+ menu.item I18n.t("actions.hidden", scope: "decidim.moderations"),
43
+ decidim_admin.moderations_path(hidden: true),
44
+ position: 2,
45
+ active: params[:hidden].present?
46
+ end
47
+ end
48
+
49
+ initializer "decidim_admin.admin_settings_menu" do
50
+ Decidim.menu :admin_settings_menu do |menu|
51
+ menu.item I18n.t("menu.configuration", scope: "decidim.admin"),
52
+ decidim_admin.edit_organization_path,
53
+ position: 1.0,
54
+ if: allowed_to?(:update, :organization, organization: current_organization),
55
+ active: is_active_link?(decidim_admin.edit_organization_path)
56
+
57
+ menu.item I18n.t("menu.appearance", scope: "decidim.admin"),
58
+ decidim_admin.edit_organization_appearance_path,
59
+ position: 1.1,
60
+ if: allowed_to?(:update, :organization, organization: current_organization),
61
+ active: is_active_link?(decidim_admin.edit_organization_appearance_path)
62
+
63
+ menu.item I18n.t("menu.homepage", scope: "decidim.admin"),
64
+ decidim_admin.edit_organization_homepage_path,
65
+ position: 1.2,
66
+ if: allowed_to?(:update, :organization, organization: current_organization),
67
+ active: is_active_link?(decidim_admin.edit_organization_homepage_path, %r{^/admin/organization/homepage})
68
+
69
+ menu.item I18n.t("menu.scopes", scope: "decidim.admin"),
70
+ decidim_admin.scopes_path,
71
+ position: 1.3,
72
+ if: allowed_to?(:read, :scope),
73
+ active: is_active_link?(decidim_admin.scopes_path)
74
+ menu.item I18n.t("menu.scope_types", scope: "decidim.admin"),
75
+ decidim_admin.scope_types_path,
76
+ position: 1.4,
77
+ if: allowed_to?(:read, :scope_type),
78
+ active: is_active_link?(decidim_admin.scope_types_path)
79
+ menu.item I18n.t("menu.areas", scope: "decidim.admin"),
80
+ decidim_admin.areas_path,
81
+ position: 1.5,
82
+ if: allowed_to?(:read, :area),
83
+ active: is_active_link?(decidim_admin.areas_path)
84
+
85
+ menu.item I18n.t("menu.area_types", scope: "decidim.admin"),
86
+ decidim_admin.area_types_path,
87
+ position: 1.6,
88
+ if: allowed_to?(:read, :area_type),
89
+ active: is_active_link?(decidim_admin.area_types_path)
90
+
91
+ menu.item I18n.t("menu.help_sections", scope: "decidim.admin"),
92
+ decidim_admin.help_sections_path,
93
+ position: 1.6,
94
+ if: allowed_to?(:update, :help_sections),
95
+ active: is_active_link?(decidim_admin.help_sections_path)
96
+ end
97
+ end
98
+
35
99
  initializer "decidim_admin.menu" do
36
100
  Decidim.menu :admin_menu do |menu|
37
101
  menu.item I18n.t("menu.dashboard", scope: "decidim.admin"),
@@ -40,10 +104,20 @@ module Decidim
40
104
  position: 1,
41
105
  active: ["decidim/admin/dashboard" => :show]
42
106
 
107
+ menu.item I18n.t("menu.moderation", scope: "decidim.admin"),
108
+ decidim_admin.moderations_path,
109
+ icon_name: "flag",
110
+ position: 4,
111
+ active: [%w(
112
+ decidim/admin/global_moderations
113
+ decidim/admin/global_moderations/reports
114
+ ), []],
115
+ if: allowed_to?(:read, :global_moderation)
116
+
43
117
  menu.item I18n.t("menu.static_pages", scope: "decidim.admin"),
44
118
  decidim_admin.static_pages_path,
45
119
  icon_name: "book",
46
- position: 4,
120
+ position: 4.5,
47
121
  active: [%w(
48
122
  decidim/admin/static_pages
49
123
  decidim/admin/static_page_topics
@@ -60,6 +134,7 @@ module Decidim
60
134
  decidim/admin/user_groups_csv_verifications
61
135
  decidim/admin/officializations
62
136
  decidim/admin/impersonatable_users
137
+ decidim/admin/moderated_users
63
138
  decidim/admin/managed_users/impersonation_logs
64
139
  decidim/admin/managed_users/promotions
65
140
  decidim/admin/authorization_workflows
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Admin
5
+ module Import
6
+ autoload :ImporterFactory, "decidim/admin/import/importer_factory"
7
+ autoload :Importer, "decidim/admin/import/importer"
8
+ autoload :Creator, "decidim/admin/import/creator"
9
+ autoload :Readers, "decidim/admin/import/readers"
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Admin
5
+ module Import
6
+ # This is an abstract class with a very naive default implementation
7
+ # for the importers to use. It can also serve as a superclass of your
8
+ # own implementation.
9
+ #
10
+ # It is used to be run against each element of an importable collection
11
+ # in order to parse relevant fields. Every import should specify their
12
+ # own creator or this default will be used.
13
+ class Creator
14
+ attr_reader :data
15
+
16
+ # Initializes the creator with a resource.
17
+ #
18
+ # data - The data hash to parse.
19
+ # context - The context needed by the producer
20
+ def initialize(data, context = nil)
21
+ @data = data.except(:id, "id")
22
+ @context = context
23
+ end
24
+
25
+ # Retuns the resource class to be created with the provided data.
26
+ def self.resource_klass
27
+ raise NotImplementedError, "#{self.class.name} does not define resource class"
28
+ end
29
+
30
+ # Can be used to convert the data hash to the resource attributes in
31
+ # case the data hash to be imported has different column names than the
32
+ # resource object to be created of it.
33
+ #
34
+ # By default returns the data hash but can be implemented by each creator
35
+ # implementation.
36
+ #
37
+ # Returns the resource attributes to be passed for the constructor.
38
+ def resource_attributes
39
+ @data
40
+ end
41
+
42
+ # Public: Returns a created object with the parsed data.
43
+ #
44
+ # Returns a target object.
45
+ def produce
46
+ self.class.resource_klass.new(resource_attributes)
47
+ end
48
+
49
+ def finish!
50
+ resource.save!
51
+ end
52
+
53
+ private
54
+
55
+ def resource
56
+ raise NotImplementedError, "#{self.class.name} does not define resource"
57
+ end
58
+
59
+ #
60
+ # Collect field's language specified cells to one hash
61
+ #
62
+ # field - The field name eg. "title"
63
+ # locales - Available locales
64
+ #
65
+ # Returns the hash including locale-imported_data pairs. eg. {en: "Heading", ca: "Cap", es: "Bóveda"}
66
+ #
67
+ def locale_hasher(field, locales)
68
+ return data[field.to_sym] if data.has_key?(field.to_sym)
69
+
70
+ hash = {}
71
+ locales.each do |locale|
72
+ parsed = data[:"#{field}/#{locale}"]
73
+ next if parsed.nil?
74
+
75
+ hash[locale] = parsed
76
+ end
77
+ hash
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Admin
5
+ module Import
6
+ # Class providing the interface and implementation of an importer. Needs
7
+ # a reader to be passed to the constructor which handles the import file
8
+ # reading depending on its type.
9
+ #
10
+ # You can also use the ImporterFactory class to create an Importer
11
+ # instance.
12
+ class Importer
13
+ # Public: Initializes an Importer.
14
+ #
15
+ # file - A file with the data to be imported.
16
+ # reader - A Reader to be used to read the data from the file.
17
+ # creator - A Creator to be used during the import.
18
+ # context - A hash including component specific data.
19
+ def initialize(file:, reader: Readers::Base, creator: Creator, context: nil)
20
+ @file = file
21
+ @reader = reader
22
+ @creator = creator
23
+ @context = context
24
+ end
25
+
26
+ # Import data and create resources
27
+ #
28
+ # Returns an array of resources
29
+ def prepare
30
+ @prepare ||= collection.map(&:produce)
31
+ end
32
+
33
+ # Save resources
34
+ def import!
35
+ collection.map(&:finish!)
36
+ end
37
+
38
+ # Returns a collection of creators
39
+ def collection
40
+ @collection ||= collection_data.map { |item| creator.new(item, context) }
41
+ end
42
+
43
+ # Returns array of all resource indexes where validations fail.
44
+ def invalid_lines
45
+ @invalid_lines ||= check_invalid_lines(prepare)
46
+ end
47
+
48
+ private
49
+
50
+ attr_reader :file, :reader, :creator, :context
51
+
52
+ def collection_data
53
+ return @collection_data if @collection_data
54
+
55
+ @collection_data = []
56
+ data_headers = []
57
+ reader.new(file).read_rows do |rowdata, index|
58
+ if index.zero?
59
+ data_headers = rowdata.map(&:to_sym)
60
+ else
61
+ @collection_data << Hash[
62
+ rowdata.each_with_index.map do |val, ind|
63
+ [data_headers[ind], val]
64
+ end
65
+ ]
66
+ end
67
+ end
68
+
69
+ @collection_data
70
+ end
71
+
72
+ def check_invalid_lines(imported_data)
73
+ invalid_lines = []
74
+ imported_data.each_with_index do |record, index|
75
+ invalid_lines << index + 1 unless record.valid?
76
+ end
77
+ invalid_lines
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Admin
5
+ module Import
6
+ # A factory class providing easier way to create new importers.
7
+ class ImporterFactory
8
+ def self.build(file, mime_type, **keyword_args)
9
+ reader = Readers.search_by_mime_type(mime_type)
10
+ raise NotImplementedError, "No reader implemented for mime type: #{mime_type}" if reader.nil?
11
+
12
+ Importer.new(file: file, reader: reader, **keyword_args)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Admin
5
+ module Import
6
+ module Readers
7
+ autoload :Base, "decidim/admin/import/readers/base"
8
+ autoload :CSV, "decidim/admin/import/readers/csv"
9
+ autoload :JSON, "decidim/admin/import/readers/json"
10
+ autoload :XLS, "decidim/admin/import/readers/xls"
11
+
12
+ # Accepted mime types
13
+ # keys: are used for dynamic help text on admin form.
14
+ # values: are used to validate the file format of imported document.
15
+ ACCEPTED_MIME_TYPES = {
16
+ json: Readers::JSON::MIME_TYPE,
17
+ csv: Readers::CSV::MIME_TYPE,
18
+ xls: Readers::XLS::MIME_TYPE
19
+ }.freeze
20
+
21
+ def self.all
22
+ [
23
+ Readers::CSV,
24
+ Readers::JSON,
25
+ Readers::XLS
26
+ ]
27
+ end
28
+
29
+ def self.search_by_mime_type(mime_type)
30
+ all.each do |reader_klass|
31
+ return reader_klass if mime_type == reader_klass::MIME_TYPE
32
+ end
33
+
34
+ nil
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end