decidim-initiatives 0.30.1 → 0.31.0.rc1
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.
- checksums.yaml +4 -4
- data/README.md +46 -9
- data/app/cells/decidim/initiatives/content_blocks/highlighted_initiatives_settings_form/show.erb +7 -2
- data/app/cells/decidim/initiatives/initiative_g_cell.rb +5 -1
- data/app/commands/decidim/initiatives/admin/publish_initiative.rb +1 -5
- data/app/commands/decidim/initiatives/admin/update_initiative.rb +1 -2
- data/app/commands/decidim/initiatives/create_initiative.rb +0 -1
- data/app/commands/decidim/initiatives/update_initiative.rb +1 -3
- data/app/commands/decidim/initiatives/vote_initiative.rb +1 -11
- data/app/controllers/concerns/decidim/initiatives/has_signature_workflow.rb +36 -0
- data/app/controllers/concerns/decidim/initiatives/needs_initiative.rb +1 -12
- data/app/controllers/decidim/initiatives/admin/initiatives_controller.rb +2 -2
- data/app/controllers/decidim/initiatives/admin/initiatives_settings_controller.rb +1 -1
- data/app/controllers/decidim/initiatives/admin/initiatives_type_scopes_controller.rb +2 -2
- data/app/controllers/decidim/initiatives/admin/initiatives_types_controller.rb +2 -2
- data/app/controllers/decidim/initiatives/committee_requests_controller.rb +10 -2
- data/app/controllers/decidim/initiatives/create_initiative_controller.rb +84 -18
- data/app/controllers/decidim/initiatives/initiative_signatures_controller.rb +133 -42
- data/app/controllers/decidim/initiatives/initiative_votes_controller.rb +3 -2
- data/app/controllers/decidim/initiatives/initiatives_controller.rb +21 -2
- data/app/forms/decidim/initiatives/admin/initiative_form.rb +0 -1
- data/app/forms/decidim/initiatives/initiative_form.rb +0 -3
- data/app/helpers/decidim/initiatives/application_helper.rb +2 -0
- data/app/helpers/decidim/initiatives/initiatives_helper.rb +0 -1
- data/app/models/decidim/initiative.rb +7 -31
- data/app/models/decidim/initiatives_committee_member.rb +1 -1
- data/app/models/decidim/initiatives_type.rb +5 -2
- data/app/models/decidim/initiatives_vote.rb +2 -2
- data/app/packs/entrypoints/decidim_initiatives.js +1 -1
- data/app/packs/entrypoints/decidim_initiatives_admin.scss +1 -1
- data/app/packs/src/decidim/initiatives/admin/initiatives_types.js +2 -11
- data/app/packs/src/decidim/initiatives/admin/invite_users.js +1 -1
- data/app/packs/src/decidim/initiatives/application.js +1 -1
- data/app/packs/src/decidim/initiatives/check_code.js +114 -0
- data/app/packs/src/decidim/initiatives/initiative_creation_wizard.js +16 -0
- data/app/packs/src/decidim/initiatives/scoped_type.js +1 -1
- data/app/packs/stylesheets/initiatives.scss +16 -2
- data/app/permissions/decidim/initiatives/admin/permissions.rb +4 -7
- data/app/permissions/decidim/initiatives/permissions.rb +26 -16
- data/app/presenters/decidim/initiative_presenter.rb +12 -6
- data/app/presenters/decidim/initiatives/admin_log/initiative_presenter.rb +1 -2
- data/app/queries/decidim/initiatives/initiatives_stats_followers_count.rb +14 -0
- data/app/queries/decidim/initiatives/initiatives_stats_participants_count.rb +14 -0
- data/app/serializers/decidim/initiatives/open_data_initiative_serializer.rb +0 -1
- data/app/services/decidim/initiatives/data_encryptor.rb +1 -1
- data/app/services/decidim/initiatives/legacy_signature_handler.rb +25 -0
- data/app/services/decidim/initiatives/progress_notifier.rb +1 -7
- data/app/services/decidim/initiatives/signature_handler.rb +248 -0
- data/app/services/decidim/initiatives/status_change_notifier.rb +1 -7
- data/app/views/decidim/initiatives/admin/committee_requests/index.html.erb +29 -11
- data/app/views/decidim/initiatives/admin/exports/_dropdown.html.erb +17 -20
- data/app/views/decidim/initiatives/admin/initiatives/_form.html.erb +7 -13
- data/app/views/decidim/initiatives/admin/initiatives/_initiative_attachments.erb +2 -2
- data/app/views/decidim/initiatives/admin/initiatives/index.html.erb +76 -47
- data/app/views/decidim/initiatives/admin/initiatives_types/_form.html.erb +13 -21
- data/app/views/decidim/initiatives/admin/initiatives_types/_initiative_type_scopes.html.erb +28 -12
- data/app/views/decidim/initiatives/admin/initiatives_types/index.html.erb +33 -15
- data/app/views/decidim/initiatives/create_initiative/_committee_member.html.erb +27 -0
- data/app/views/decidim/initiatives/create_initiative/_return_to_initiatives_button.html.erb +3 -0
- data/app/views/decidim/initiatives/create_initiative/_send_to_technical_validation_button.html.erb +10 -0
- data/app/views/decidim/initiatives/create_initiative/_share_committee_link.html.erb +5 -1
- data/app/views/decidim/initiatives/create_initiative/fill_data.html.erb +7 -11
- data/app/views/decidim/initiatives/create_initiative/finish.html.erb +16 -13
- data/app/views/decidim/initiatives/create_initiative/promotal_committee.html.erb +33 -6
- data/app/views/decidim/initiatives/create_initiative/select_initiative_type.html.erb +40 -26
- data/app/views/decidim/initiatives/initiative_signatures/_sms_code_form.html.erb +22 -0
- data/app/views/decidim/initiatives/initiative_signatures/_sms_phone_number_form.html.erb +13 -0
- data/app/views/decidim/initiatives/initiative_signatures/fill_personal_data.html.erb +23 -22
- data/app/views/decidim/initiatives/initiative_signatures/finish.html.erb +17 -5
- data/app/views/decidim/initiatives/initiative_signatures/sms_code.html.erb +6 -8
- data/app/views/decidim/initiatives/initiative_signatures/sms_phone_number.html.erb +3 -8
- data/app/views/decidim/initiatives/initiative_signatures/update_buttons_and_counters.js.erb +3 -14
- data/app/views/decidim/initiatives/initiative_votes/update_buttons_and_counters.js.erb +3 -14
- data/app/views/decidim/initiatives/initiatives/_committee_members.html.erb +1 -1
- data/app/views/decidim/initiatives/initiatives/_form.html.erb +1 -3
- data/app/views/decidim/initiatives/initiatives/_new_initiative_button.html.erb +10 -3
- data/app/views/decidim/initiatives/initiatives/_pending_initiatives.html.erb +5 -0
- data/app/views/decidim/initiatives/initiatives/index.html.erb +8 -0
- data/app/views/decidim/initiatives/initiatives/show.html.erb +2 -2
- data/app/views/layouts/decidim/_initiative_signature_creation_header.html.erb +20 -2
- data/app/views/layouts/decidim/admin/_manage_initiatives.html.erb +1 -1
- data/app/views/layouts/decidim/initiative_signature_creation.html.erb +3 -1
- data/config/assets.rb +2 -2
- data/config/locales/ar.yml +0 -45
- data/config/locales/bg.yml +0 -54
- data/config/locales/ca-IT.yml +99 -51
- data/config/locales/ca.yml +99 -51
- data/config/locales/cs.yml +93 -54
- data/config/locales/de.yml +100 -52
- data/config/locales/el.yml +0 -45
- data/config/locales/en.yml +99 -51
- data/config/locales/es-MX.yml +99 -51
- data/config/locales/es-PY.yml +99 -51
- data/config/locales/es.yml +99 -51
- data/config/locales/eu.yml +120 -72
- data/config/locales/fi-plain.yml +99 -51
- data/config/locales/fi.yml +99 -51
- data/config/locales/fr-CA.yml +44 -51
- data/config/locales/fr.yml +44 -51
- data/config/locales/ga-IE.yml +0 -17
- data/config/locales/gl.yml +0 -41
- data/config/locales/hu.yml +0 -54
- data/config/locales/id-ID.yml +0 -40
- data/config/locales/is-IS.yml +0 -22
- data/config/locales/it.yml +0 -53
- data/config/locales/ja.yml +98 -49
- data/config/locales/lb.yml +0 -50
- data/config/locales/lt.yml +0 -56
- data/config/locales/lv.yml +0 -46
- data/config/locales/nl.yml +0 -47
- data/config/locales/no.yml +0 -53
- data/config/locales/pl.yml +0 -56
- data/config/locales/pt-BR.yml +0 -53
- data/config/locales/pt.yml +0 -53
- data/config/locales/ro-RO.yml +92 -50
- data/config/locales/ru.yml +0 -25
- data/config/locales/sk.yml +0 -43
- data/config/locales/sl.yml +0 -1
- data/config/locales/sv.yml +10 -53
- data/config/locales/tr-TR.yml +0 -53
- data/config/locales/uk.yml +0 -25
- data/config/locales/zh-CN.yml +0 -45
- data/config/locales/zh-TW.yml +0 -53
- data/db/migrate/20250605104500_remove_hashtag_column_initiatives.rb +7 -0
- data/lib/decidim/api/initiative_api_type.rb +3 -0
- data/lib/decidim/api/initiative_type.rb +23 -4
- data/lib/decidim/exporters/initiative_votes_pdf.rb +1 -1
- data/lib/decidim/initiatives/default_signature_authorizer.rb +17 -0
- data/lib/decidim/initiatives/engine.rb +17 -14
- data/lib/decidim/initiatives/menu.rb +1 -1
- data/lib/decidim/initiatives/participatory_space.rb +15 -1
- data/lib/decidim/initiatives/seeds.rb +1 -2
- data/lib/decidim/initiatives/signature_workflow_manifest.rb +176 -0
- data/lib/decidim/initiatives/signatures.rb +12 -0
- data/lib/decidim/initiatives/test/factories.rb +7 -7
- data/lib/decidim/initiatives/test/initiatives_signatures_test_helpers.rb +19 -0
- data/lib/decidim/initiatives/validatable_authorizations.rb +83 -0
- data/lib/decidim/initiatives/version.rb +1 -1
- data/lib/decidim/initiatives.rb +23 -12
- metadata +33 -21
- data/app/events/decidim/initiatives/endorse_initiative_event.rb +0 -13
- data/app/forms/decidim/initiatives/vote_form.rb +0 -208
- data/app/packs/src/decidim/initiatives/identity_selector_dialog.js +0 -14
- data/app/services/decidim/initiatives/pdf_signature_example.rb +0 -110
- data/app/views/decidim/initiatives/initiative_signatures/_wizard_steps.html.erb +0 -15
- data/app/views/decidim/initiatives/initiatives/_interactions.html.erb +0 -10
- data/app/views/layouts/decidim/_initiative_header.html.erb +0 -27
data/config/locales/zh-TW.yml
CHANGED
@@ -7,9 +7,7 @@ zh-TW:
|
|
7
7
|
answer_url: 回答 URL
|
8
8
|
area_id: 區域
|
9
9
|
decidim_scope_id: 範圍
|
10
|
-
decidim_user_group_id: 作者
|
11
10
|
description: 說明
|
12
|
-
hashtag: 主題標籤
|
13
11
|
offline_votes: 親筆簽名
|
14
12
|
offline_votes_for_scope: '%{scope_name} 的親筆簽名'
|
15
13
|
scope_id: 範圍
|
@@ -36,7 +34,6 @@ zh-TW:
|
|
36
34
|
comments_enabled: 啟用評論
|
37
35
|
custom_signature_end_date_enabled: 允許作者選擇結束簽名收集期限
|
38
36
|
description: 說明
|
39
|
-
document_number_authorization_handler: 授權核准文件編號以驗證簽名
|
40
37
|
extra_fields_legal_information: 關於個人資料蒐集的法律資訊
|
41
38
|
minimum_committee_members: 委員會成員最少人數
|
42
39
|
online_signature_enabled: 啟用線上簽名
|
@@ -86,14 +83,11 @@ zh-TW:
|
|
86
83
|
label: 狀態
|
87
84
|
values:
|
88
85
|
accepted: 足夠的簽署數
|
89
|
-
created: 已建立
|
90
86
|
discarded: 已捨棄
|
91
87
|
rejected: 不足夠的簽署數
|
92
88
|
validating: 技術驗證
|
93
89
|
type_id_eq:
|
94
90
|
label: 類別
|
95
|
-
search_placeholder:
|
96
|
-
title_or_description_or_id_string_or_author_name_or_author_nickname_cont: 透過標題、描述、ID 或作者姓名搜尋 %{collection}
|
97
91
|
initiatives_settings:
|
98
92
|
update:
|
99
93
|
success: 倡議設定已成功更新.
|
@@ -279,7 +273,6 @@ zh-TW:
|
|
279
273
|
edit:
|
280
274
|
update: 更新
|
281
275
|
form:
|
282
|
-
authorizations: 權限設置
|
283
276
|
options: 選項
|
284
277
|
initiative_type_scopes:
|
285
278
|
title: 倡議類型範圍
|
@@ -302,7 +295,6 @@ zh-TW:
|
|
302
295
|
update: "%{user_name} 更新了 %{resource_name} 倡議類型"
|
303
296
|
admin_states:
|
304
297
|
accepted: 足夠的簽署數
|
305
|
-
created: 已建立
|
306
298
|
discarded: 已捨棄
|
307
299
|
rejected: 不足夠的簽署數
|
308
300
|
validating: 技術驗證
|
@@ -331,37 +323,20 @@ zh-TW:
|
|
331
323
|
name: 重點倡議
|
332
324
|
create_initiative:
|
333
325
|
fill_data:
|
334
|
-
back: 返回
|
335
326
|
continue: 繼續
|
336
327
|
fill_data_help: "<ul> <li>檢閱您倡議的內容。標題是否易於理解?倡議的目標是否清晰明確?</li> <li>您需要選擇簽名的類型。是現場簽名、線上簽名還是兩者的組合?</li> <li>倡議的地理範圍是什麼?</li> </ul>"
|
337
|
-
more_information: "(更多資訊)"
|
338
328
|
select_area: 選擇一個地區
|
339
329
|
select_scope: 選擇一個類型
|
340
330
|
finish:
|
341
331
|
back: 返回
|
342
|
-
back_to_initiatives: 回到倡議
|
343
|
-
confirm: 您即將發送倡議給管理員進行審核和發佈。一旦發佈,您將無法編輯它。您確定要繼續嗎?"
|
344
|
-
edit_my_initiative: 編輯我的倡議
|
345
|
-
go_to_my_initiatives: 前往我的倡議
|
346
|
-
more_information: "(更多資訊)"
|
347
|
-
send_my_initiative: 將我的倡議送交技術審核
|
348
|
-
finish_help:
|
349
|
-
publish_helper_text: 請記住,要使您的倡議能夠被發佈,您必須填寫必要的資訊並將其<strong>送交技術審核</strong>以供管理員審查。
|
350
332
|
previous_form:
|
351
333
|
back: 返回
|
352
|
-
continue: 繼續
|
353
|
-
promotal_committee:
|
354
|
-
individual_help_text: 這種倡議需要至少 %{committee_size} 人(證明者)組成推廣委員會。您必須與參與該倡議的其他人分享以下鏈接。當您的聯繫人收到此鏈接後,他們將需要按照指示進行相應步驟。
|
355
|
-
more_information: "(更多資訊)"
|
356
334
|
select_initiative_type:
|
357
335
|
back: 返回
|
358
336
|
choose_html: 我想要創建一個<strong>%{title}</strong>
|
359
337
|
more_information: (更多資訊)
|
360
338
|
select: 我想推動這個倡議
|
361
|
-
select_initiative_type_help: 倡議是參與者可以通過其來干預,以便組織可以為捍衛公共利益而采取行動的手段。您希望發起哪個倡議?
|
362
339
|
verification_required: 驗證您的帳戶以推動這個倡議
|
363
|
-
share_committee_link:
|
364
|
-
invite_to_committee_help: 邀請成為推動委員會成員的人的連結
|
365
340
|
edit:
|
366
341
|
accept: 接受倡議
|
367
342
|
back: 返回
|
@@ -383,11 +358,6 @@ zh-TW:
|
|
383
358
|
email_outro: 您收到此通知,是因為您正在關注 %{author_nickname}。您可以使用上面的連結停止接收通知。
|
384
359
|
email_subject: 由 %{author_nickname} 提出的新倡議
|
385
360
|
notification_title: 倡議 <a href="%{resource_path}">%{resource_title}</a> 由 <a href="%{author_path}">%{author_name} %{author_nickname}</a> 提出。
|
386
|
-
endorse_initiative_event:
|
387
|
-
email_intro: "\"%{author_name} %{author_nickname} 正在追蹤,並已連署以下倡議,或許你想參與對話:"
|
388
|
-
email_outro: 您收到此通知,是因為您正在關注 %{author_nickname}。您可以使用上面的連結停止接收通知。
|
389
|
-
email_subject: 倡議得到 %{author_nickname} 的連署
|
390
|
-
notification_title: <a href="%{resource_path}">%{resource_title}</a> 倡議已獲 %{author_name} %{author_nickname} 連署。
|
391
361
|
revoke_membership_request:
|
392
362
|
email_intro: "%{author_nickname} 拒絕了您加入 %{resource_title} 倡議發起委員會的申請。"
|
393
363
|
email_outro: '這是您收到的通知,因為您申請參與這個倡議:%{resource_title}。'
|
@@ -402,23 +372,14 @@ zh-TW:
|
|
402
372
|
uninitialized: 尚未由管理員設置倡議。
|
403
373
|
initiative_signatures:
|
404
374
|
fill_personal_data:
|
405
|
-
continue: 繼續
|
406
375
|
help: 以下請填寫您的個人資料以簽署此倡議。
|
407
376
|
finish:
|
408
377
|
back_to_initiative: 回到倡議
|
409
|
-
sms_code:
|
410
|
-
continue: 檢查代碼並繼續
|
411
|
-
help: 請檢查您手機收到的SMS簡訊
|
412
|
-
sms_phone_number:
|
413
|
-
continue: 發送簡訊給我
|
414
|
-
help: 請填寫您驗證過的手機號碼以申請驗證碼.
|
415
378
|
initiative_votes:
|
416
379
|
create:
|
417
380
|
error: 發起倡議的簽署遇到問題。
|
418
381
|
invalid: 提供的資料以簽署此倡議為無效.
|
419
382
|
success_html: 恭喜!<strong> %{title} </strong> 倡議已成功簽署。
|
420
|
-
personal_data:
|
421
|
-
invalid: 個人資料與授權提供的資料不一致。
|
422
383
|
sms_code:
|
423
384
|
invalid: 您的驗證碼與我們的不符。請仔細檢查我們發送給您的SMS簡訊。
|
424
385
|
sms_phone:
|
@@ -449,10 +410,6 @@ zh-TW:
|
|
449
410
|
initiatives:
|
450
411
|
closed_initiatives_warning: 目前沒有開放中的倡議,但您可以在這裡找到所有已結束的倡議清單。
|
451
412
|
no_initiatives_warning: 沒有符合您的搜尋條件的倡議。
|
452
|
-
interactions:
|
453
|
-
comments_count:
|
454
|
-
count:
|
455
|
-
other: 評論
|
456
413
|
orders:
|
457
414
|
label: '按照以下方式對倡議進行排序:'
|
458
415
|
most_commented: 最多評論
|
@@ -517,7 +474,6 @@ zh-TW:
|
|
517
474
|
show:
|
518
475
|
badge_name:
|
519
476
|
accepted: 足夠的簽署數
|
520
|
-
created: 已建立
|
521
477
|
discarded: 已捨棄
|
522
478
|
rejected: 簽署數不足
|
523
479
|
validating: 技術驗證
|
@@ -536,20 +492,11 @@ zh-TW:
|
|
536
492
|
initiatives_type:
|
537
493
|
actions:
|
538
494
|
title: 操作
|
539
|
-
vote: 簽署
|
540
495
|
layouts:
|
541
496
|
decidim:
|
542
497
|
initiative_creation_header:
|
543
498
|
fill_data: 建立
|
544
|
-
finish: 完成
|
545
|
-
promotal_committee: 推動委員會
|
546
499
|
select_initiative_type: 選擇
|
547
|
-
initiative_signature_creation_header:
|
548
|
-
fill_personal_data: 填寫您的資料
|
549
|
-
finish: 完成
|
550
|
-
sms_code: SMS短訊代碼驗證碼
|
551
|
-
sms_phone_number: 行動電話號碼
|
552
|
-
title: 簽名 %{initiative_title}
|
553
500
|
initiatives:
|
554
501
|
no_initiatives_yet:
|
555
502
|
no_initiatives_yet: 尚無倡議!
|
@@ -8,8 +8,11 @@ module Decidim
|
|
8
8
|
graphql_name "InitiativeType"
|
9
9
|
description "An initiative type"
|
10
10
|
|
11
|
+
field :attachments_enabled, GraphQL::Types::Boolean, "Enable attachments on initiative types", null: true
|
11
12
|
field :banner_image, GraphQL::Types::String, "Banner image", null: true
|
12
13
|
field :collect_user_extra_fields, GraphQL::Types::Boolean, "Collect participant personal data on signature", null: true
|
14
|
+
field :comments_enabled, GraphQL::Types::Boolean, "Enable comments on initiative types", null: true
|
15
|
+
field :custom_signature_end_date_enabled, GraphQL::Types::Boolean, "Enable participants to set custom signature end date", null: true
|
13
16
|
field :description, Decidim::Core::TranslatedFieldType, "This is the initiative type description", null: true
|
14
17
|
field :extra_fields_legal_information, GraphQL::Types::String, "Legal information about the collection of personal data", null: true
|
15
18
|
field :id, GraphQL::Types::ID, "The internal ID for this initiative type", null: false
|
@@ -9,13 +9,19 @@ module Decidim
|
|
9
9
|
implements Decidim::Core::AttachableInterface
|
10
10
|
implements Decidim::Initiatives::InitiativeTypeInterface
|
11
11
|
implements Decidim::Core::TimestampsInterface
|
12
|
+
implements Decidim::Core::FollowableInterface
|
13
|
+
implements Decidim::Core::ReferableInterface
|
14
|
+
implements Decidim::Comments::CommentableInterface
|
12
15
|
|
13
16
|
description "A initiative"
|
14
17
|
|
18
|
+
field :answer, Decidim::Core::TranslatedFieldType, "The answer of the initiative", null: true
|
19
|
+
field :answer_url, GraphQL::Types::String, "The answer url of the initiative", null: true
|
20
|
+
field :answered_at, Decidim::Core::DateTimeType, "The date this initiative was answered", null: true
|
15
21
|
field :author, Decidim::Core::AuthorInterface, "The initiative author", null: false
|
16
22
|
field :committee_members, [Decidim::Initiatives::InitiativeCommitteeMemberType, { null: true }], "The committee members list", null: true
|
17
23
|
field :description, Decidim::Core::TranslatedFieldType, "The description of this initiative.", null: true
|
18
|
-
field :
|
24
|
+
field :first_progress_notification_at, Decidim::Core::DateTimeType, "The date when the first progress notification was sent ", null: true
|
19
25
|
field :initiative_supports_count, GraphQL::Types::Int,
|
20
26
|
description: "The number of supports in this initiative",
|
21
27
|
method: :online_votes_count,
|
@@ -28,15 +34,28 @@ module Decidim
|
|
28
34
|
field :offline_votes, GraphQL::Types::Int, "The number of offline votes in this initiative", method: :offline_votes_count, null: true
|
29
35
|
field :online_votes, GraphQL::Types::Int, "The number of online votes in this initiative", method: :online_votes_count, null: true
|
30
36
|
field :published_at, Decidim::Core::DateTimeType, "The time this initiative was published", null: false
|
31
|
-
field :
|
37
|
+
field :second_progress_notification_at, Decidim::Core::DateTimeType, "The date when the second progress notification was sent", null: true
|
32
38
|
field :signature_end_date, Decidim::Core::DateType, "The signature end date", null: false
|
33
39
|
field :signature_start_date, Decidim::Core::DateType, "The signature start date", null: false
|
34
40
|
field :signature_type, GraphQL::Types::String, "Signature type of the initiative", null: true
|
35
41
|
field :slug, GraphQL::Types::String, "The slug of the initiative", null: false
|
36
42
|
field :state, GraphQL::Types::String, "Current status of the initiative", null: true
|
43
|
+
field :url, GraphQL::Types::String, "The URL of this initiative", null: true
|
37
44
|
|
38
|
-
def
|
39
|
-
object.
|
45
|
+
def url
|
46
|
+
Decidim::EngineRouter.main_proxy(object).initiative_url(object)
|
47
|
+
end
|
48
|
+
|
49
|
+
def answer
|
50
|
+
return unless object.answered?
|
51
|
+
|
52
|
+
object.answer
|
53
|
+
end
|
54
|
+
|
55
|
+
def answer_url
|
56
|
+
return unless object.answered?
|
57
|
+
|
58
|
+
object.answer_url
|
40
59
|
end
|
41
60
|
end
|
42
61
|
end
|
@@ -148,7 +148,7 @@ module Decidim
|
|
148
148
|
end
|
149
149
|
|
150
150
|
def encryptor
|
151
|
-
@encryptor ||= Decidim::Initiatives::DataEncryptor.new(secret:
|
151
|
+
@encryptor ||= Decidim::Initiatives::DataEncryptor.new(secret: Decidim::Initiatives.signature_handler_encryption_secret)
|
152
152
|
end
|
153
153
|
|
154
154
|
def truncate(text, length = 50)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Initiatives
|
5
|
+
class DefaultSignatureAuthorizer < Decidim::Verifications::DefaultActionAuthorizer
|
6
|
+
#
|
7
|
+
# Initializes the DefaultActionAuthorizer class.
|
8
|
+
#
|
9
|
+
# authorization - The existing authorization record to be evaluated. Can be nil.
|
10
|
+
# options - A hash with options related only to the current authorization process.
|
11
|
+
#
|
12
|
+
def initialize(authorization, options = {})
|
13
|
+
super(authorization, options, nil, nil)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -22,6 +22,7 @@ module Decidim
|
|
22
22
|
|
23
23
|
resources :create_initiative do
|
24
24
|
collection do
|
25
|
+
get :load_initiative_draft
|
25
26
|
get :select_initiative_type
|
26
27
|
put :select_initiative_type, to: "create_initiative#store_initiative_type"
|
27
28
|
get :fill_data
|
@@ -60,6 +61,7 @@ module Decidim
|
|
60
61
|
get :authorization_create_modal, to: "authorization_create_modals#show"
|
61
62
|
get :print, to: "initiatives#print", as: "print"
|
62
63
|
get :send_to_technical_validation, to: "initiatives#send_to_technical_validation"
|
64
|
+
delete :discard, to: "initiatives#discard"
|
63
65
|
end
|
64
66
|
|
65
67
|
resource :initiative_vote, only: [:create, :destroy]
|
@@ -99,6 +101,15 @@ module Decidim
|
|
99
101
|
Decidim.icons.register(name: "forbid-line", icon: "forbid-line", category: "system", description: "", engine: :initiatives)
|
100
102
|
end
|
101
103
|
|
104
|
+
initializer "decidim_initiatives.stats" do
|
105
|
+
Decidim.stats.register :initiatives_count,
|
106
|
+
priority: StatsRegistry::HIGH_PRIORITY,
|
107
|
+
icon_name: "lightbulb-flash-line",
|
108
|
+
tooltip_key: "initiatives_count_tooltip" do |organization, _start_at, _end_at|
|
109
|
+
Decidim::Initiative.where(organization:).public_spaces.count
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
102
113
|
initializer "decidim_initiatives.content_blocks" do
|
103
114
|
Decidim::Initiatives::ContentBlocks::RegistryManager.register!
|
104
115
|
end
|
@@ -118,20 +129,12 @@ module Decidim
|
|
118
129
|
Decidim::Gamification.register_badge(:initiatives) do |badge|
|
119
130
|
badge.levels = [1, 5, 15, 30, 50]
|
120
131
|
|
121
|
-
badge.valid_for = [:user
|
132
|
+
badge.valid_for = [:user]
|
122
133
|
|
123
134
|
badge.reset = lambda { |model|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
author: model,
|
128
|
-
user_group: nil
|
129
|
-
).published.count
|
130
|
-
when UserGroup
|
131
|
-
Decidim::Initiative.where(
|
132
|
-
user_group: model
|
133
|
-
).published.count
|
134
|
-
end
|
135
|
+
Decidim::Initiative.where(
|
136
|
+
author: model
|
137
|
+
).published.count
|
135
138
|
}
|
136
139
|
end
|
137
140
|
end
|
@@ -140,7 +143,7 @@ module Decidim
|
|
140
143
|
Decidim::Api::QueryType.include QueryExtensions
|
141
144
|
end
|
142
145
|
|
143
|
-
initializer "decidim_initiatives.
|
146
|
+
initializer "decidim_initiatives.shakapacker.assets_path" do
|
144
147
|
Decidim.register_assets_path File.expand_path("app/packs", root)
|
145
148
|
end
|
146
149
|
|
@@ -149,7 +152,7 @@ module Decidim
|
|
149
152
|
# We need to make sure we call `Preview.all` before requiring our
|
150
153
|
# previews, otherwise any previews the app attempts to add need to be
|
151
154
|
# manually required.
|
152
|
-
if Rails.env.
|
155
|
+
if Rails.env.local?
|
153
156
|
ActionMailer::Preview.all
|
154
157
|
|
155
158
|
Dir[root.join("spec/mailers/previews/**/*_preview.rb")].each do |file|
|
@@ -113,7 +113,7 @@ module Decidim
|
|
113
113
|
decidim_admin_initiatives.initiative_share_tokens_path(current_participatory_space),
|
114
114
|
active: is_active_link?(decidim_admin_initiatives.initiative_share_tokens_path(current_participatory_space)),
|
115
115
|
icon_name: "share-line",
|
116
|
-
if: allowed_to?(:read, :
|
116
|
+
if: allowed_to?(:read, :share_token, current_participatory_space:)
|
117
117
|
end
|
118
118
|
end
|
119
119
|
|
@@ -32,7 +32,21 @@ Decidim.register_participatory_space(:initiatives) do |participatory_space|
|
|
32
32
|
|
33
33
|
participatory_space.register_resource(:initiatives_type) do |resource|
|
34
34
|
resource.model_class_name = "Decidim::InitiativesType"
|
35
|
-
resource.actions = %w(
|
35
|
+
resource.actions = %w(create)
|
36
|
+
end
|
37
|
+
|
38
|
+
participatory_space.register_stat :followers_count,
|
39
|
+
priority: Decidim::StatsRegistry::MEDIUM_PRIORITY,
|
40
|
+
icon_name: "user-follow-line",
|
41
|
+
tooltip_key: "followers_count_tooltip" do
|
42
|
+
Decidim::Initiatives::InitiativesStatsFollowersCount.for(participatory_space)
|
43
|
+
end
|
44
|
+
|
45
|
+
participatory_space.register_stat :participants_count,
|
46
|
+
priority: Decidim::StatsRegistry::MEDIUM_PRIORITY,
|
47
|
+
icon_name: "user-line",
|
48
|
+
tooltip_key: "participants_count_tooltip" do
|
49
|
+
Decidim::Initiatives::InitiativesStatsParticipantsCount.for(participatory_space)
|
36
50
|
end
|
37
51
|
|
38
52
|
participatory_space.model_class_name = "Decidim::Initiative"
|
@@ -9,7 +9,7 @@ module Decidim
|
|
9
9
|
def call
|
10
10
|
create_content_block!
|
11
11
|
|
12
|
-
|
12
|
+
number_of_records.times do |_n|
|
13
13
|
type = create_initiative_type!
|
14
14
|
|
15
15
|
organization.top_scopes.each do |scope|
|
@@ -19,7 +19,6 @@ module Decidim
|
|
19
19
|
|
20
20
|
Decidim::Initiative.states.keys.each do |state|
|
21
21
|
Decidim::Initiative.skip_callback(:save, :after, :notify_state_change, raise: false)
|
22
|
-
Decidim::Initiative.skip_callback(:create, :after, :notify_creation, raise: false)
|
23
22
|
|
24
23
|
initiative = create_initiative!(state:)
|
25
24
|
|
@@ -0,0 +1,176 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# require "decidim/settings_manifest"
|
4
|
+
require "decidim/initiatives/default_signature_authorizer"
|
5
|
+
|
6
|
+
module Decidim
|
7
|
+
module Initiatives
|
8
|
+
# This class serves as a DSL to declaratively specify a signature method.
|
9
|
+
#
|
10
|
+
# To define a direct signature method, you need to specify the `form`
|
11
|
+
# attribute as a `Decidim::Form` that will be valid if the signature
|
12
|
+
# process is valid. If no form is provided the application assumes that the
|
13
|
+
# form class is `Decidim::Initiatives::SignatureHandler`
|
14
|
+
#
|
15
|
+
# All the attributes except the name are optional. If no attributes are set
|
16
|
+
# there are default values for them and the signature flow will be direct
|
17
|
+
# without steps and metadata stored in the initiatives_vote
|
18
|
+
#
|
19
|
+
# Signature workflow attributes:
|
20
|
+
# - :form (String) (optional) The name of the form object class responsible
|
21
|
+
# for collecting and validating the data to create the initiative votes.
|
22
|
+
# This class should be inherited from
|
23
|
+
# Decidim::Initiatives::SignatureHandler and can define a set of
|
24
|
+
# attributes to collect user personal data. If extra attributes are
|
25
|
+
# defined a collect personal data step will be enabled. This class also
|
26
|
+
# can define an unique_id to avoid duplicated votes based on the
|
27
|
+
# personal data and a metadata hash that will be encrypted in the vote
|
28
|
+
# creation. The class can also collect a hash of metadata that will be
|
29
|
+
# passed to an authorization handler if defined in the workflow. The
|
30
|
+
# class is also responsible to define the scopes associated with the
|
31
|
+
# votes. The main class by default detects the scopes candidates and
|
32
|
+
# the inherited class can define a signature_scope_id based on the data
|
33
|
+
# provided by the user.
|
34
|
+
# (default: "Decidim::Initiatives::SignatureHandler")
|
35
|
+
# - :authorization_handler_form (String) (optional) If this authorization
|
36
|
+
# handler class name is set the previous form will create and validate
|
37
|
+
# an instance of it from the params defined in it (by default the
|
38
|
+
# collected metadata and the user). If the authorization is invalid the
|
39
|
+
# signature is blocked. (default: nil)
|
40
|
+
# - :save_authorizations (Boolean) (optional) This option allows the
|
41
|
+
# workflow to save or update if already exist the authorization
|
42
|
+
# associated to the previous authorization handler. Note that if this
|
43
|
+
# option is set to false the user will be required to have been
|
44
|
+
# previously authorized with the method associated to the authorization
|
45
|
+
# handler. The authorization is searched by the organization, the user
|
46
|
+
# and the authorization handler name. If this class is not defined,
|
47
|
+
# class Decidim::Initiatives::DefaultSignatureAuthorizer is used,
|
48
|
+
# which inherits from Decidim::Verifications::DefaultActionAuthorizer
|
49
|
+
# and checks the authorization status. (default: true)
|
50
|
+
# - :ephemeral (Boolean) (optional) This option enables the possibility for
|
51
|
+
# users to sign without prior registration through an ephemeral session.
|
52
|
+
# To allow ephemeral sessions to be recovered o transferred to regular
|
53
|
+
# users authorizations must be stored in the process so an
|
54
|
+
# authorization_handler_form must be defined and the save_authorizations
|
55
|
+
# option must not be set to false. If those settings are not properly
|
56
|
+
# configured this option will be ignored and the workflow will not
|
57
|
+
# allow ephemeral sessions. (default: false)
|
58
|
+
# - :promote_authorization_validation_errors (Boolean) (optional) If set
|
59
|
+
# to true, errors in the personal data passed to the authorization
|
60
|
+
# handler form will be displayed next to the corresponding fields
|
61
|
+
# in the collection of personal data. Note that this option may provide
|
62
|
+
# information about personal data to the user. (default: false)
|
63
|
+
# - :action_authorizer (String) This is the name of the action authorizer
|
64
|
+
# class responsible for checking the status of the authorization
|
65
|
+
# associated to the signature. If this class is not defined, the
|
66
|
+
# authorization status will be ignored. You can define a handler
|
67
|
+
# inherited from Decidim::Initiatives::DefaultSignatureAuthorizer which
|
68
|
+
# inherits from Decidim::Verifications::DefaultActionAuthorizer and
|
69
|
+
# checks the authorization status with an instance initialized only
|
70
|
+
# with the authorization (without a component or a resource).
|
71
|
+
# (default: nil)
|
72
|
+
# - :sms_verification (Boolean) (optional) This option enables an
|
73
|
+
# additional SMS verification step. It uses by default the sms
|
74
|
+
# verification flow defined in decidim_verifications and expects the
|
75
|
+
# user to have previously created an SMS authorization validating
|
76
|
+
# their phone number. This behaviour can be changed defining the
|
77
|
+
# following attributes. (default: false)
|
78
|
+
# - :sms_mobile_phone_form_class (String) (optional) The name of the class
|
79
|
+
# responsible for starting the users phone verification. It uses the
|
80
|
+
# default form defined in decidim_initiatives.
|
81
|
+
# (default: "Decidim::Verifications::Sms::MobilePhoneForm")
|
82
|
+
# - :sms_mobile_phone_validator (String) (optional) The name of the command
|
83
|
+
# class responsible for checking if the mobile phone provided by the
|
84
|
+
# user has an authorization associated to the sms_mobile_form_class
|
85
|
+
# and delivering the sms code
|
86
|
+
# (default: "Decidim::Initiatives::ValidateMobilePhone")
|
87
|
+
# - :sms_code_validator_class (String) (optional) The name of the command
|
88
|
+
# class responsible for checking if the SMS code provided by the user
|
89
|
+
# is valid. (default: "Decidim::Initiatives::ValidateSmsCode")
|
90
|
+
#
|
91
|
+
# An example of declaration of a workflow:
|
92
|
+
#
|
93
|
+
# Decidim::Initiatives::Signatures.register_workflow(:dummy_signature_handler) do |workflow|
|
94
|
+
# workflow.form = "DummySignatureHandler"
|
95
|
+
# workflow.authorization_handler_form = "DummyAuthorizationHandler"
|
96
|
+
# workflow.action_authorizer = "DummySignatureHandler::DummySignatureActionAuthorizer"
|
97
|
+
# workflow.promote_authorization_validation_errors = true
|
98
|
+
# workflow.sms_verification = true
|
99
|
+
# end
|
100
|
+
#
|
101
|
+
class SignatureWorkflowManifest
|
102
|
+
include ActiveModel::Model
|
103
|
+
include Decidim::AttributeObject::Model
|
104
|
+
|
105
|
+
attribute :name, String
|
106
|
+
attribute :form, String
|
107
|
+
attribute :authorization_handler_form, String, default: nil
|
108
|
+
attribute :action_authorizer, String
|
109
|
+
attribute :save_authorizations, Boolean, default: true
|
110
|
+
attribute :promote_authorization_validation_errors, Boolean, default: false
|
111
|
+
attribute :ephemeral, Boolean, default: false
|
112
|
+
attribute :sms_verification, Boolean, default: false
|
113
|
+
attribute :sms_mobile_phone_form, String, default: nil
|
114
|
+
attribute :sms_mobile_phone_validator, String, default: nil
|
115
|
+
attribute :sms_code_validator, String, default: nil
|
116
|
+
|
117
|
+
validates :name, presence: true
|
118
|
+
validate :ephemeral_configuration
|
119
|
+
|
120
|
+
alias key name
|
121
|
+
|
122
|
+
def fullname
|
123
|
+
I18n.t("#{key}.name", scope: "decidim.signature_workflows", default: name.humanize)
|
124
|
+
end
|
125
|
+
|
126
|
+
def signature_form_class
|
127
|
+
form&.safe_constantize || Decidim::Initiatives::SignatureHandler
|
128
|
+
end
|
129
|
+
|
130
|
+
def action_authorizer_class
|
131
|
+
return if action_authorizer.blank?
|
132
|
+
|
133
|
+
action_authorizer.safe_constantize || DefaultSignatureAuthorizer
|
134
|
+
end
|
135
|
+
|
136
|
+
def authorization_handler_form_class
|
137
|
+
authorization_handler_form&.safe_constantize
|
138
|
+
end
|
139
|
+
|
140
|
+
# If no authorization handler is set or the save_authorizations option
|
141
|
+
# is disabled the workflow will not be able to save the user verification
|
142
|
+
# attributes necessary to recover the user session or transfer their
|
143
|
+
# activities
|
144
|
+
def ephemeral?
|
145
|
+
return if authorization_handler_form_class.blank? || !save_authorizations
|
146
|
+
|
147
|
+
ephemeral
|
148
|
+
end
|
149
|
+
|
150
|
+
def sms_mobile_phone_form_class
|
151
|
+
return unless sms_verification
|
152
|
+
|
153
|
+
sms_mobile_phone_form&.safe_constantize || Decidim::Verifications::Sms::MobilePhoneForm
|
154
|
+
end
|
155
|
+
|
156
|
+
def sms_mobile_phone_validator_class
|
157
|
+
return unless sms_verification
|
158
|
+
|
159
|
+
sms_mobile_phone_validator&.safe_constantize || Decidim::Initiatives::ValidateMobilePhone
|
160
|
+
end
|
161
|
+
|
162
|
+
def sms_code_validator_class
|
163
|
+
return unless sms_verification
|
164
|
+
|
165
|
+
sms_code_validator&.safe_constantize || Decidim::Initiatives::ValidateSmsCode
|
166
|
+
end
|
167
|
+
|
168
|
+
def ephemeral_configuration
|
169
|
+
return unless Rails.env.development?
|
170
|
+
return unless ephemeral
|
171
|
+
|
172
|
+
raise StandardError, "Wrong configuration of ephemeral signature workflow #{fullname}" if !save_authorizations || authorization_handler_form.blank?
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Initiatives
|
5
|
+
module Signatures
|
6
|
+
autoload :SignatureWorkflowManifest, "decidim/initiatives/signature_workflow_manifest"
|
7
|
+
include Decidim::HasWorkflows
|
8
|
+
|
9
|
+
def self.workflow_manifest_class = SignatureWorkflowManifest
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -84,13 +84,17 @@ FactoryBot.define do
|
|
84
84
|
end
|
85
85
|
|
86
86
|
trait :with_user_extra_fields_collection do
|
87
|
-
collect_user_extra_fields { true }
|
88
87
|
extra_fields_legal_information { generate_localized_description(:initiatives_type_extra_fields_legal_information, skip_injection:) }
|
89
|
-
document_number_authorization_handler { "
|
88
|
+
document_number_authorization_handler { "dummy_signature_with_personal_data_handler" }
|
90
89
|
end
|
91
90
|
|
92
91
|
trait :with_sms_code_validation do
|
93
|
-
|
92
|
+
document_number_authorization_handler { "dummy_signature_with_sms_handler" }
|
93
|
+
end
|
94
|
+
|
95
|
+
trait :with_sms_code_validation_and_user_extra_fields_collection do
|
96
|
+
extra_fields_legal_information { generate_localized_description(:initiatives_type_extra_fields_legal_information, skip_injection:) }
|
97
|
+
document_number_authorization_handler { "dummy_signature_handler" }
|
94
98
|
end
|
95
99
|
|
96
100
|
trait :child_scope_threshold_enabled do
|
@@ -268,10 +272,6 @@ FactoryBot.define do
|
|
268
272
|
end
|
269
273
|
initiative { create(:initiative, skip_injection:) }
|
270
274
|
author { create(:user, :confirmed, organization: initiative.organization, skip_injection:) }
|
271
|
-
decidim_user_group_id { create(:user_group, skip_injection:).id }
|
272
|
-
after(:create) do |support, evaluator|
|
273
|
-
create(:user_group_membership, user: support.author, user_group: Decidim::UserGroup.find(support.decidim_user_group_id), skip_injection: evaluator.skip_injection)
|
274
|
-
end
|
275
275
|
end
|
276
276
|
|
277
277
|
factory :initiatives_committee_member, class: "Decidim::InitiativesCommitteeMember" do
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Initiatives
|
5
|
+
module InitiativesSignaturesTestHelpers
|
6
|
+
def fill_signature_date(date)
|
7
|
+
[date.year, date.month, date.day].each_with_index do |value, i|
|
8
|
+
within "select[name='dummy_signature_handler[date_of_birth(#{i + 1}i)]']" do
|
9
|
+
find("option[value='#{value}']").select_option
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
RSpec.configure do |config|
|
18
|
+
config.include Decidim::Initiatives::InitiativesSignaturesTestHelpers, type: :system
|
19
|
+
end
|