From e1325a0f23be73491c36dfe0f99db27309a97167 Mon Sep 17 00:00:00 2001 From: Iva Date: Fri, 13 Sep 2024 11:17:57 +0200 Subject: [PATCH 01/43] Add feature flag --- back/config/schemas/settings.schema.json.erb | 12 ++++++++++++ .../commercial/multi_tenancy/db/seeds/tenants.rb | 4 ++++ 2 files changed, 16 insertions(+) diff --git a/back/config/schemas/settings.schema.json.erb b/back/config/schemas/settings.schema.json.erb index 580b6a0dc8dc..11a7baf5b81f 100644 --- a/back/config/schemas/settings.schema.json.erb +++ b/back/config/schemas/settings.schema.json.erb @@ -1316,6 +1316,18 @@ } }, + "input_cosponsorship": { + "type": "object", + "title": "Input co-sponsorship", + "description": "Enables the ability to invite co-sponsors to your inputs.", + "additionalProperties": false, + "required": ["allowed", "enabled"], + "properties": { + "allowed": { "type": "boolean", "default": false }, + "enabled": { "type": "boolean", "default": false } + } + }, + "management_feed": { "type": "object", "title": "Management Feed", diff --git a/back/engines/commercial/multi_tenancy/db/seeds/tenants.rb b/back/engines/commercial/multi_tenancy/db/seeds/tenants.rb index 720816f470bb..c3063978bea2 100644 --- a/back/engines/commercial/multi_tenancy/db/seeds/tenants.rb +++ b/back/engines/commercial/multi_tenancy/db/seeds/tenants.rb @@ -453,6 +453,10 @@ def create_localhost_tenant enabled: true, allowed: true }, + input_cosponsorship: { + enabled: true, + allowed: true + }, management_feed: { enabled: true, allowed: true From 5330b4fe1c2e71ee8ceefc176d479f1870c4beb8 Mon Sep 17 00:00:00 2001 From: Iva Date: Mon, 16 Sep 2024 12:02:34 +0300 Subject: [PATCH 02/43] Add custom field --- back/app/controllers/web_api/v1/ideas_controller.rb | 5 +++++ back/app/models/custom_field.rb | 6 ++++-- back/app/services/export/xlsx/value_visitor.rb | 4 ++++ back/app/services/field_visitor_service.rb | 4 ++++ back/app/services/idea_custom_fields_service.rb | 2 +- .../services/input_json_schema_generator_service.rb | 13 +++++++++++++ .../services/input_ui_schema_generator_service.rb | 4 ++++ back/config/locales/en.yml | 3 +++ back/lib/participation_method/ideation.rb | 2 +- 9 files changed, 39 insertions(+), 4 deletions(-) diff --git a/back/app/controllers/web_api/v1/ideas_controller.rb b/back/app/controllers/web_api/v1/ideas_controller.rb index cf01dcfd427c..4f2380a21146 100644 --- a/back/app/controllers/web_api/v1/ideas_controller.rb +++ b/back/app/controllers/web_api/v1/ideas_controller.rb @@ -205,6 +205,7 @@ def update extract_custom_field_values_from_params!(input.custom_form) params[:idea][:topic_ids] ||= [] if params[:idea].key?(:topic_ids) + params[:idea][:cosponsor_ids] ||= [] if params[:idea].key?(:cosponsor_ids) params[:idea][:phase_ids] ||= [] if params[:idea].key?(:phase_ids) params_service.mark_custom_field_values_to_clear!(input.custom_field_values, params[:idea][:custom_field_values]) @@ -365,6 +366,10 @@ def idea_complex_attributes(custom_form, submittable_field_keys) complex_attributes[:topic_ids] = [] end + if submittable_field_keys.include?(:cosponsor_ids) + complex_attributes[:cosponsor_ids] = [] + end + complex_attributes end diff --git a/back/app/models/custom_field.rb b/back/app/models/custom_field.rb index c5ed69c8a901..60cba7427dcb 100644 --- a/back/app/models/custom_field.rb +++ b/back/app/models/custom_field.rb @@ -59,11 +59,11 @@ class CustomField < ApplicationRecord INPUT_TYPES = %w[ checkbox date file_upload files html html_multiloc image_files linear_scale multiline_text multiline_text_multiloc multiselect multiselect_image number page point line polygon select select_image shapefile_upload text text_multiloc - topic_ids section + topic_ids section cosponsor_ids ].freeze CODES = %w[ author_id birthyear body_multiloc budget domicile education gender idea_files_attributes idea_images_attributes - ideation_section1 ideation_section2 ideation_section3 location_description proposed_budget title_multiloc topic_ids + ideation_section1 ideation_section2 ideation_section3 location_description proposed_budget title_multiloc topic_ids cosponsor_ids ].freeze VISIBLE_TO_PUBLIC = 'public' VISIBLE_TO_ADMINS = 'admins' @@ -235,6 +235,8 @@ def accept(visitor) visitor.visit_text_multiloc self when 'topic_ids' visitor.visit_topic_ids self + when 'cosponsor_ids' + visitor.visit_cosponsor_ids self else raise "Unsupported input type: #{input_type}" end diff --git a/back/app/services/export/xlsx/value_visitor.rb b/back/app/services/export/xlsx/value_visitor.rb index aaffbe079492..b51b75fbed5e 100644 --- a/back/app/services/export/xlsx/value_visitor.rb +++ b/back/app/services/export/xlsx/value_visitor.rb @@ -119,6 +119,10 @@ def visit_topic_ids(_field) topic_titles.join(VALUE_SEPARATOR) end + def visit_cosponsor_ids(_field) + return '' + end + private attr_reader :model, :option_index, :multiloc_service diff --git a/back/app/services/field_visitor_service.rb b/back/app/services/field_visitor_service.rb index 533c92951e17..fae8b3d590ce 100644 --- a/back/app/services/field_visitor_service.rb +++ b/back/app/services/field_visitor_service.rb @@ -93,6 +93,10 @@ def visit_topic_ids(field) default(field) end + def visit_cosponsor_ids(field) + default(field) + end + def visit_page(field) default(field) end diff --git a/back/app/services/idea_custom_fields_service.rb b/back/app/services/idea_custom_fields_service.rb index f9be778592b9..c3cd97f293b5 100644 --- a/back/app/services/idea_custom_fields_service.rb +++ b/back/app/services/idea_custom_fields_service.rb @@ -37,7 +37,7 @@ def submittable_fields_with_other_options # Used in the printable PDF export def printable_fields - ignore_field_types = %w[section page date files image_files point file_upload shapefile_upload topic_ids] + ignore_field_types = %w[section page date files image_files point file_upload shapefile_upload topic_ids cosponsor_ids] fields = enabled_fields.reject { |field| ignore_field_types.include? field.input_type } insert_other_option_text_fields(fields) end diff --git a/back/app/services/input_json_schema_generator_service.rb b/back/app/services/input_json_schema_generator_service.rb index 8d833f9bad22..733cba329802 100644 --- a/back/app/services/input_json_schema_generator_service.rb +++ b/back/app/services/input_json_schema_generator_service.rb @@ -54,4 +54,17 @@ def visit_topic_ids(field) end } end + + def visit_cosponsor_ids(field) + return super unless field.code == 'cosponsor_ids' + + { + type: 'array', + uniqueItems: true, + minItems: field.enabled? && field.required? ? 1 : 0, + items: { + type: 'string' + } + } + end end diff --git a/back/app/services/input_ui_schema_generator_service.rb b/back/app/services/input_ui_schema_generator_service.rb index 7311f9aadbff..082ccfc8f742 100644 --- a/back/app/services/input_ui_schema_generator_service.rb +++ b/back/app/services/input_ui_schema_generator_service.rb @@ -28,6 +28,10 @@ def visit_topic_ids(field) default field end + def visit_cosponsor_ids(field) + default field + end + def visit_page(field) { type: 'Page', diff --git a/back/config/locales/en.yml b/back/config/locales/en.yml index b701a0bd74d9..56fbf7174551 100644 --- a/back/config/locales/en.yml +++ b/back/config/locales/en.yml @@ -170,6 +170,9 @@ en: topic_ids: title: Tags description: + consponsor_ids: + title: Co-sponsors + description: location: title: Location description: diff --git a/back/lib/participation_method/ideation.rb b/back/lib/participation_method/ideation.rb index 767e75d04e4f..c235c2e2cf16 100644 --- a/back/lib/participation_method/ideation.rb +++ b/back/lib/participation_method/ideation.rb @@ -7,7 +7,7 @@ def self.method_str end def allowed_extra_field_input_types - %w[section number linear_scale text multiline_text select multiselect multiselect_image] + %w[section number linear_scale text multiline_text select multiselect multiselect_image cosponsor_ids] end def allowed_ideas_orders From 6976483beefadede604aa011ef133513bd7b4f82 Mon Sep 17 00:00:00 2001 From: Iva Date: Mon, 16 Sep 2024 17:06:06 +0300 Subject: [PATCH 03/43] Add to form --- back/app/models/idea.rb | 1 + .../services/idea_custom_fields_service.rb | 2 +- .../input_json_schema_generator_service.rb | 4 +--- back/lib/participation_method/ideation.rb | 23 +++++++++++++++++++ front/app/api/custom_fields/types.ts | 3 ++- front/app/api/idea_custom_fields/types.ts | 1 + front/app/api/idea_json_form_schema/types.ts | 1 + .../FormBuilderToolbox/BuiltInFields.tsx | 9 ++++++++ .../components/FormBuilderToolbox/index.tsx | 3 +++ .../FormBuilder/components/messages.ts | 4 ++++ .../app/components/FormBuilder/edit/index.tsx | 2 ++ .../projects/project/inputForm/utils.tsx | 3 +-- 12 files changed, 49 insertions(+), 7 deletions(-) diff --git a/back/app/models/idea.rb b/back/app/models/idea.rb index 2a7bc8dadc87..d5b56ca5d6ec 100644 --- a/back/app/models/idea.rb +++ b/back/app/models/idea.rb @@ -92,6 +92,7 @@ class Idea < ApplicationRecord has_many :baskets, through: :baskets_ideas has_many :text_images, as: :imageable, dependent: :destroy has_many :followers, as: :followable, dependent: :destroy + has_many :cosponsors, class_name: 'User' has_many :idea_images, -> { order(:ordering) }, dependent: :destroy, inverse_of: :idea has_many :idea_files, -> { order(:ordering) }, dependent: :destroy, inverse_of: :idea diff --git a/back/app/services/idea_custom_fields_service.rb b/back/app/services/idea_custom_fields_service.rb index c3cd97f293b5..ea7ae702dd2b 100644 --- a/back/app/services/idea_custom_fields_service.rb +++ b/back/app/services/idea_custom_fields_service.rb @@ -43,7 +43,7 @@ def printable_fields end def importable_fields - ignore_field_types = %w[page section date files image_files file_upload shapefile_upload point line polygon] + ignore_field_types = %w[page section date files image_files file_upload shapefile_upload point line polygon cosponsor_ids] enabled_fields_with_other_options.reject { |field| ignore_field_types.include? field.input_type } end diff --git a/back/app/services/input_json_schema_generator_service.rb b/back/app/services/input_json_schema_generator_service.rb index 733cba329802..7d0d3be737e9 100644 --- a/back/app/services/input_json_schema_generator_service.rb +++ b/back/app/services/input_json_schema_generator_service.rb @@ -55,9 +55,7 @@ def visit_topic_ids(field) } end - def visit_cosponsor_ids(field) - return super unless field.code == 'cosponsor_ids' - + def visit_cosponsor_ids(field) { type: 'array', uniqueItems: true, diff --git a/back/lib/participation_method/ideation.rb b/back/lib/participation_method/ideation.rb index c235c2e2cf16..c88ce3371d84 100644 --- a/back/lib/participation_method/ideation.rb +++ b/back/lib/participation_method/ideation.rb @@ -270,6 +270,29 @@ def default_fields(custom_form) enabled: true, ordering: 8, answer_visible_to: CustomField::VISIBLE_TO_PUBLIC + ), + CustomField.new( + id: SecureRandom.uuid, + resource: custom_form, + key: 'cosponsor_ids', + code: 'cosponsor_ids', + input_type: 'text', + title_multiloc: multiloc_service.i18n_to_multiloc( + 'custom_fields.ideas.consponsor_ids.title', + locales: CL2_SUPPORTED_LOCALES + ), + description_multiloc: begin + multiloc_service.i18n_to_multiloc( + 'custom_fields.ideas.consponsor_ids.description', + locales: CL2_SUPPORTED_LOCALES + ) + rescue StandardError + {} + end, + required: false, + enabled: false, + ordering: proposed_budget_in_form? ? 10 : 9, + answer_visible_to: CustomField::VISIBLE_TO_PUBLIC ) ] if proposed_budget_in_form? diff --git a/front/app/api/custom_fields/types.ts b/front/app/api/custom_fields/types.ts index 5714470df4f8..7b721603aa04 100644 --- a/front/app/api/custom_fields/types.ts +++ b/front/app/api/custom_fields/types.ts @@ -34,7 +34,8 @@ export type ICustomFieldInputType = | 'multiselect_image' | 'point' | 'line' - | 'polygon'; + | 'polygon' + | 'cosponsor_ids'; export type IOptionsType = { id?: string; diff --git a/front/app/api/idea_custom_fields/types.ts b/front/app/api/idea_custom_fields/types.ts index 2940586de66a..0a2a674f2b04 100644 --- a/front/app/api/idea_custom_fields/types.ts +++ b/front/app/api/idea_custom_fields/types.ts @@ -29,6 +29,7 @@ export type TCustomFieldCode = | 'title_multiloc' | 'body_multiloc' | 'topic_ids' + | 'cosponsor_ids' | 'location_description' | 'proposed_budget' | 'idea_images_attributes' diff --git a/front/app/api/idea_json_form_schema/types.ts b/front/app/api/idea_json_form_schema/types.ts index b5a2403dd432..cd513b1cbaa3 100644 --- a/front/app/api/idea_json_form_schema/types.ts +++ b/front/app/api/idea_json_form_schema/types.ts @@ -17,6 +17,7 @@ export type CustomFieldCodes = | 'title_multiloc' | 'body_multiloc' | 'topic_ids' + | 'cosponsor_ids' | 'location_description' | 'idea_images_attributes' | 'idea_files_attributes' diff --git a/front/app/components/FormBuilder/components/FormBuilderToolbox/BuiltInFields.tsx b/front/app/components/FormBuilder/components/FormBuilderToolbox/BuiltInFields.tsx index 7fae16764ace..eac1eb30a45a 100644 --- a/front/app/components/FormBuilder/components/FormBuilderToolbox/BuiltInFields.tsx +++ b/front/app/components/FormBuilder/components/FormBuilderToolbox/BuiltInFields.tsx @@ -101,6 +101,15 @@ const BuiltInFields = ({ move, builderConfig }: BuiltInFieldsProps) => { data-cy="e2e-tags-item" /> )} + enableField('cosponsor_ids')} + data-cy="e2e-cosponsors-field" + fieldsToExclude={builderConfig.toolboxFieldsToExclude} + inputType="cosponsor_ids" + disabledTooltipMessage={messages.disabledBuiltInFieldTooltip} + /> ); }; diff --git a/front/app/components/FormBuilder/components/FormBuilderToolbox/index.tsx b/front/app/components/FormBuilder/components/FormBuilderToolbox/index.tsx index 25b7ac492e6e..9a7959e5741a 100644 --- a/front/app/components/FormBuilder/components/FormBuilderToolbox/index.tsx +++ b/front/app/components/FormBuilder/components/FormBuilderToolbox/index.tsx @@ -65,6 +65,8 @@ const FormBuilderToolbox = ({ 'toolboxTitle', messages.content ); + + console.log(formCustomFields); if (isNilOrError(locale)) return null; const addField = (inputType: ICustomFieldInputType) => { @@ -230,6 +232,7 @@ const FormBuilderToolbox = ({ inputType="file_upload" disabled={isCustomFieldsDisabled} /> + {!builderConfig.toolboxFieldsToExclude.includes('point') && ( // We want to show the mapping section <> diff --git a/front/app/components/FormBuilder/components/messages.ts b/front/app/components/FormBuilder/components/messages.ts index f8868b8debf1..8956f23ddc21 100644 --- a/front/app/components/FormBuilder/components/messages.ts +++ b/front/app/components/FormBuilder/components/messages.ts @@ -75,6 +75,10 @@ export default defineMessages({ id: 'app.components.formBuilder.fileUpload', defaultMessage: 'File upload', }, + cosponsors: { + id: 'app.components.formBuilder.cosponsors', + defaultMessage: 'Co-sponsors', + }, shapefileUpload: { id: 'app.components.formBuilder.shapefileUpload', defaultMessage: 'Esri shapefile upload', diff --git a/front/app/components/FormBuilder/edit/index.tsx b/front/app/components/FormBuilder/edit/index.tsx index d93bf6124181..930b53513fc0 100644 --- a/front/app/components/FormBuilder/edit/index.tsx +++ b/front/app/components/FormBuilder/edit/index.tsx @@ -238,6 +238,8 @@ const FormEdit = ({ maximum: field.maximum?.toString() || '5', }), })); + console.log(finalResponseArray); + await updateFormCustomFields( { projectId, diff --git a/front/app/containers/Admin/projects/project/inputForm/utils.tsx b/front/app/containers/Admin/projects/project/inputForm/utils.tsx index 68c60d457da1..8749d0b77f4d 100644 --- a/front/app/containers/Admin/projects/project/inputForm/utils.tsx +++ b/front/app/containers/Admin/projects/project/inputForm/utils.tsx @@ -32,7 +32,6 @@ export const ideationConfig: FormBuilderConfig = { 'location_description', 'idea_images_attributes', 'idea_files_attributes', - 'topic_ids', ], formCustomFields: undefined, @@ -68,7 +67,7 @@ export const proposalsConfig: FormBuilderConfig = { 'location_description', 'idea_images_attributes', 'idea_files_attributes', - 'topic_ids', + 'cosponsor_ids', ], formCustomFields: undefined, From 51a5f70c063835ccb479cc027c0b878c3fb6f758 Mon Sep 17 00:00:00 2001 From: CircleCI Date: Mon, 16 Sep 2024 14:09:14 +0000 Subject: [PATCH 04/43] Translations updated by CI (extract-intl) --- front/app/translations/en.json | 1 + 1 file changed, 1 insertion(+) diff --git a/front/app/translations/en.json b/front/app/translations/en.json index de3fa060d7b1..07b7d4b02947 100644 --- a/front/app/translations/en.json +++ b/front/app/translations/en.json @@ -684,6 +684,7 @@ "app.components.formBuilder.configureMap": "Configure map", "app.components.formBuilder.confirmLeaveBuilderButtonText": "Yes, I want to leave", "app.components.formBuilder.content": "Content", + "app.components.formBuilder.cosponsors": "Co-sponsors", "app.components.formBuilder.default": "Default", "app.components.formBuilder.defaultContent": "Default content", "app.components.formBuilder.delete": "Delete", From 506c6c3fad3f47e98c6d9ac56011e34f73271355 Mon Sep 17 00:00:00 2001 From: Iva Date: Mon, 16 Sep 2024 17:34:39 +0300 Subject: [PATCH 05/43] Add icons and copy --- back/lib/participation_method/ideation.rb | 2 +- .../FormBuilder/components/FormBuilderToolbox/index.tsx | 2 -- .../components/FormFields/FormField/IconsAndBadges/utils.ts | 2 ++ front/app/components/FormBuilder/components/FormFields/utils.ts | 2 ++ front/app/components/FormBuilder/utils.tsx | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/back/lib/participation_method/ideation.rb b/back/lib/participation_method/ideation.rb index c88ce3371d84..4b2b9d74a328 100644 --- a/back/lib/participation_method/ideation.rb +++ b/back/lib/participation_method/ideation.rb @@ -276,7 +276,7 @@ def default_fields(custom_form) resource: custom_form, key: 'cosponsor_ids', code: 'cosponsor_ids', - input_type: 'text', + input_type: 'cosponsor_ids', title_multiloc: multiloc_service.i18n_to_multiloc( 'custom_fields.ideas.consponsor_ids.title', locales: CL2_SUPPORTED_LOCALES diff --git a/front/app/components/FormBuilder/components/FormBuilderToolbox/index.tsx b/front/app/components/FormBuilder/components/FormBuilderToolbox/index.tsx index 9a7959e5741a..4c3b68ae41cc 100644 --- a/front/app/components/FormBuilder/components/FormBuilderToolbox/index.tsx +++ b/front/app/components/FormBuilder/components/FormBuilderToolbox/index.tsx @@ -66,7 +66,6 @@ const FormBuilderToolbox = ({ messages.content ); - console.log(formCustomFields); if (isNilOrError(locale)) return null; const addField = (inputType: ICustomFieldInputType) => { @@ -232,7 +231,6 @@ const FormBuilderToolbox = ({ inputType="file_upload" disabled={isCustomFieldsDisabled} /> - {!builderConfig.toolboxFieldsToExclude.includes('point') && ( // We want to show the mapping section <> diff --git a/front/app/components/FormBuilder/components/FormFields/FormField/IconsAndBadges/utils.ts b/front/app/components/FormBuilder/components/FormFields/FormField/IconsAndBadges/utils.ts index 5149ce03707e..86f2b239acf0 100644 --- a/front/app/components/FormBuilder/components/FormFields/FormField/IconsAndBadges/utils.ts +++ b/front/app/components/FormBuilder/components/FormFields/FormField/IconsAndBadges/utils.ts @@ -20,6 +20,8 @@ const getBuiltinFieldIcon = (key: string): IconNames => { return 'upload-file'; case 'proposed_budget': return 'money-bag'; + case 'cosponsor_ids': + return 'volunteer'; default: return 'survey'; } diff --git a/front/app/components/FormBuilder/components/FormFields/utils.ts b/front/app/components/FormBuilder/components/FormFields/utils.ts index 38f4a6800061..b830f679dbbd 100644 --- a/front/app/components/FormBuilder/components/FormFields/utils.ts +++ b/front/app/components/FormBuilder/components/FormFields/utils.ts @@ -50,6 +50,8 @@ const getBuiltinFieldBadgeLabel = (key: string): MessageDescriptor => { return messages.fileUpload; case 'proposed_budget': return messages.proposedBudget; + case 'cosponsor_ids': + return messages.cosponsors; default: return messages.default; } diff --git a/front/app/components/FormBuilder/utils.tsx b/front/app/components/FormBuilder/utils.tsx index 55fc3dbe44dd..568672ac5bc2 100644 --- a/front/app/components/FormBuilder/utils.tsx +++ b/front/app/components/FormBuilder/utils.tsx @@ -31,7 +31,7 @@ export const builtInFieldKeys = [ 'location_description', 'idea_images_attributes', 'idea_files_attributes', - 'topic_ids', + 'cosponsor_ids', ]; export type BuiltInKeyType = (typeof builtInFieldKeys)[number]; From c42a0198086ff484151efb9b8e039423e3d51e56 Mon Sep 17 00:00:00 2001 From: Iva Date: Tue, 17 Sep 2024 12:22:51 +0300 Subject: [PATCH 06/43] Add field to form --- Makefile | 36 +++--- .../Components/Controls/CosponsorsControl.tsx | 105 ++++++++++++++++++ .../Form/Components/Controls/index.tsx | 5 + .../Form/Components/Controls/messages.ts | 4 + .../Form/Components/Fields/formConfig.tsx | 3 + .../FormBuilderToolbox/ToolboxItem.tsx | 2 +- .../components/FormBuilderToolbox/index.tsx | 7 +- 7 files changed, 138 insertions(+), 24 deletions(-) create mode 100644 front/app/components/Form/Components/Controls/CosponsorsControl.tsx diff --git a/Makefile b/Makefile index aad4dfe2db46..105f60a4a928 100644 --- a/Makefile +++ b/Makefile @@ -13,22 +13,22 @@ # ================= build: - docker-compose build + docker compose build cd front && npm install reset-dev-env: # -v removes volumes with all the data inside https://docs.docker.com/compose/reference/down/ - docker-compose down -v || true # do not exit on error (some networks may be present, volumes may be used, which is often fine) + docker compose down -v || true # do not exit on error (some networks may be present, volumes may be used, which is often fine) make build # https://citizenlabco.slack.com/archives/C016C2EHURY/p1644234622002569 - docker-compose run --rm web "bin/rails db:create && bin/rails db:reset" - docker-compose run --rm -e RAILS_ENV=test web bin/rails db:drop db:create db:schema:load + docker compose run --rm web "bin/rails db:create && bin/rails db:reset" + docker compose run --rm -e RAILS_ENV=test web bin/rails db:drop db:create db:schema:load migrate: - docker-compose run --rm web bin/rails db:migrate cl2back:clean_tenant_settings email_campaigns:assure_campaign_records fix_existing_tenants:update_permissions cl2back:clear_cache_store email_campaigns:remove_deprecated + docker compose run --rm web bin/rails db:migrate cl2back:clean_tenant_settings email_campaigns:assure_campaign_records fix_existing_tenants:update_permissions cl2back:clear_cache_store email_campaigns:remove_deprecated be-up: - docker-compose up + docker compose up fe-up: cd front && npm start @@ -41,7 +41,7 @@ up: # # or # make rails-console c rails-console: - docker-compose run --rm web bin/rails c + docker compose run --rm web bin/rails c # Runs rails console in an existing web container. May be useful if you need to access localhost:4000 in the console. # E.g., this command works in this console `curl http://localhost:4000` @@ -50,7 +50,7 @@ rails-console-exec: # search_path=localhost specifies the schema of localhost tenant psql: - docker-compose run -it -e PGPASSWORD=postgres -e PGOPTIONS="--search_path=localhost" postgres psql -U postgres -h postgres -d cl2_back_development + docker compose run -it -e PGPASSWORD=postgres -e PGOPTIONS="--search_path=localhost" postgres psql -U postgres -h postgres -d cl2_back_development # Run it with: # make copy-paste-code-entity source=initiative_resubmitted_for_review target=new_cosponsor_added @@ -64,12 +64,12 @@ blint back-lint-autocorrect: # Usage example: # make r file=spec/models/idea_spec.rb r rspec: - docker-compose run --rm web bin/rspec ${file} + docker compose run --rm web bin/rspec ${file} # Usage example: # make feature-toggle feature=initiative_cosponsors enabled=true feature-toggle: - docker-compose run web "bin/rails runner \"enabled = ${enabled}; feature = '${feature}'; Tenant.find_by(host: 'localhost').switch!; c = AppConfiguration.instance; c.settings['${feature}'] ||= {}; c.settings['${feature}']['allowed'] = ${enabled}; c.settings['${feature}']['enabled'] = ${enabled}; c.save!\"" + docker compose run web "bin/rails runner \"enabled = ${enabled}; feature = '${feature}'; Tenant.find_by(host: 'localhost').switch!; c = AppConfiguration.instance; c.settings['${feature}'] ||= {}; c.settings['${feature}']['allowed'] = ${enabled}; c.settings['${feature}']['enabled'] = ${enabled}; c.save!\"" # ================= # E2E tests @@ -80,8 +80,8 @@ feature-toggle: # After running this command, start the dev servers as usual (make up) e2e-setup: make build - docker-compose run --rm web bin/rails db:drop db:create db:schema:load - docker-compose run --rm web bin/rails cl2_back:create_tenant[localhost,e2etests_template] + docker compose run --rm web bin/rails db:drop db:create db:schema:load + docker compose run --rm web bin/rails cl2_back:create_tenant[localhost,e2etests_template] e2e-setup-and-up: make e2e-setup @@ -97,18 +97,18 @@ e2e-run-test: # ----------------- # The following e2e commands use the "ci-env" prefix which means -# that the used environment will be very similar to CI (the same docker-compose.yml file) +# that the used environment will be very similar to CI (the same docker compose.yml file) # ----------------- e2e-ci-env-setup: cd e2e && \ - docker-compose build && \ - docker-compose run web bin/rails db:drop db:create db:schema:load && \ - docker-compose run web bin/rails "cl2_back:create_tenant[e2e.front,e2etests_template]" + docker compose build && \ + docker compose run web bin/rails db:drop db:create db:schema:load && \ + docker compose run web bin/rails "cl2_back:create_tenant[e2e.front,e2etests_template]" e2e-ci-env-up: # we need --build because volumes are not used by default https://www.notion.so/citizenlab/Testing-253d0c3cd99841a59929f7f615179935?pvs=4#f088eb9d2c304af59d5d5d2ede6e4439 - cd e2e && docker-compose up --build + cd e2e && docker compose up --build e2e-ci-env-setup-and-up: make e2e-ci-env-setup @@ -120,7 +120,7 @@ e2e-ci-env-setup-and-up: # make e2e-ci-env-run-test spec=cypress/e2e/project_description_builder/sections e2e-ci-env-run-test: cd e2e && \ - docker-compose run --rm --name cypress_run front npm run cypress:run -- --config baseUrl=http://e2e.front:3000 --spec ${spec} + docker compose run --rm --name cypress_run front npm run cypress:run -- --config baseUrl=http://e2e.front:3000 --spec ${spec} e2e-ci-env-db-dump: cd e2e && \ diff --git a/front/app/components/Form/Components/Controls/CosponsorsControl.tsx b/front/app/components/Form/Components/Controls/CosponsorsControl.tsx new file mode 100644 index 000000000000..bca9d4121c48 --- /dev/null +++ b/front/app/components/Form/Components/Controls/CosponsorsControl.tsx @@ -0,0 +1,105 @@ +import React, { useState } from 'react'; + +import { Box } from '@citizenlab/cl2-component-library'; +import { + ControlProps, + RankedTester, + rankWith, + scopeEndsWith, +} from '@jsonforms/core'; +import { withJsonFormsControlProps } from '@jsonforms/react'; +import { WrappedComponentProps } from 'react-intl'; +import { MentionItem } from 'react-mentions'; + +import { FormLabel } from 'components/UI/FormComponents'; +import MentionsTextArea from 'components/UI/MentionsTextArea'; + +import { useIntl } from 'utils/cl-intl'; +import { getLabel, sanitizeForClassname } from 'utils/JSONFormUtils'; + +import ErrorDisplay from '../ErrorDisplay'; + +import { getSubtextElement } from './controlUtils'; +import messages from './messages'; + +const cosponsorships: any = []; + +const CosponsorsControl = ({ + uischema, + schema, + data, + handleChange, + path, + errors, + required, + visible, + id, +}: ControlProps & WrappedComponentProps) => { + const initialCosponsorsText = cosponsorships + ? cosponsorships.reduce( + (acc, cosponsorship) => + `${acc}@[${cosponsorship.name}](${cosponsorship.user_id}) `, + '' + ) + : null; + const [cosponsorsText, setCosponsorsText] = useState( + initialCosponsorsText + ); + const { formatMessage } = useIntl(); + const [didBlur, setDidBlur] = useState(false); + + if (!visible) { + return null; + } + + const handleOnChangeInputField = (text: string) => { + setCosponsorsText(text); + }; + + return ( + <> + + + + + { + handleOnChangeInputField(text); + }} + onChangeMentions={(mentions: MentionItem[]) => { + const user_ids = mentions.map((user) => user.id); + handleChange(path, user_ids); + }} + placeholder={formatMessage(messages.cosponsorsPlaceholder)} + onBlur={() => setDidBlur(true)} + showUniqueUsers + value={cosponsorsText} + /> + + + ); +}; + +export default withJsonFormsControlProps(CosponsorsControl); + +export const cosponsorsControlTester: RankedTester = rankWith( + 1000, + scopeEndsWith('cosponsor_ids') +); diff --git a/front/app/components/Form/Components/Controls/index.tsx b/front/app/components/Form/Components/Controls/index.tsx index 404c9ce583a8..795ba5349603 100644 --- a/front/app/components/Form/Components/Controls/index.tsx +++ b/front/app/components/Form/Components/Controls/index.tsx @@ -54,6 +54,9 @@ import OrderedLayout, { orderedLayoutTester, } from 'components/Form/Components/Layouts/OrderedLayout'; +import CosponsorsControl, { + cosponsorsControlTester, +} from './CosponsorsControl'; import ImageMultichoiceControl, { imageMultichoiceControlTester, } from './ImageMultichoiceControl'; @@ -135,4 +138,6 @@ export { singleAttachmentControlTester, ShapefileUploadControl, shapefileUploadControlTester, + CosponsorsControl, + cosponsorsControlTester, }; diff --git a/front/app/components/Form/Components/Controls/messages.ts b/front/app/components/Form/Components/Controls/messages.ts index eff7414420fa..0c2fbabf9e02 100644 --- a/front/app/components/Form/Components/Controls/messages.ts +++ b/front/app/components/Form/Components/Controls/messages.ts @@ -108,4 +108,8 @@ export default defineMessages({ id: 'app.components.form.controls.valueOutOfTotal', defaultMessage: '{value} out of {total}', }, + cosponsorsPlaceholder: { + id: 'app.components.form.controls.cosponsorsPlaceholder', + defaultMessage: 'Start typing a name to search', + }, }); diff --git a/front/app/components/Form/Components/Fields/formConfig.tsx b/front/app/components/Form/Components/Fields/formConfig.tsx index 3a9a81db491a..0c6bb3ddd4ec 100644 --- a/front/app/components/Form/Components/Fields/formConfig.tsx +++ b/front/app/components/Form/Components/Fields/formConfig.tsx @@ -54,6 +54,8 @@ import { SingleAttachmentControl, shapefileUploadControlTester, ShapefileUploadControl, + CosponsorsControl, + cosponsorsControlTester, } from 'components/Form/Components/Controls'; const commonRenderers = [ @@ -78,6 +80,7 @@ const commonRenderers = [ { tester: userPickerControlTester, renderer: UserPickerControl }, { tester: multilocInputTester, renderer: MultilocInputLayout }, { tester: orderedLayoutTester, renderer: OrderedLayout }, + { tester: cosponsorsControlTester, renderer: CosponsorsControl }, ]; export const selectRenderers = (formType: 'default' | 'input' | 'survey') => { diff --git a/front/app/components/FormBuilder/components/FormBuilderToolbox/ToolboxItem.tsx b/front/app/components/FormBuilder/components/FormBuilderToolbox/ToolboxItem.tsx index 4901941a66fb..ab17c3febd01 100644 --- a/front/app/components/FormBuilder/components/FormBuilderToolbox/ToolboxItem.tsx +++ b/front/app/components/FormBuilder/components/FormBuilderToolbox/ToolboxItem.tsx @@ -31,7 +31,6 @@ interface Props { const AddIcon = styled(Icon).attrs({ name: 'plus' })` margin-left: auto; - margin-right: 12px; fill: ${colors.textSecondary}; margin-right: 0; `; @@ -94,6 +93,7 @@ const ToolboxItem = ({ )} - + {!builderConfig.alwaysShowCustomFields && ( <IconTooltip - ml="4px" icon={isCustomFieldsDisabled ? 'info-outline' : 'info-solid'} iconColor={ isCustomFieldsDisabled ? colors.coolGrey300 : colors.coolGrey500 } placement="right-start" - py="0px" + ml="4px" content={ <Box> <Text my="4px" color="white" fontSize="s"> From ff4f118b50effc3eafdb0bda8f621594978fd218 Mon Sep 17 00:00:00 2001 From: CircleCI <hello@citizenlab.co> Date: Tue, 17 Sep 2024 09:26:14 +0000 Subject: [PATCH 07/43] Translations updated by CI (extract-intl) --- front/app/translations/en.json | 1 + 1 file changed, 1 insertion(+) diff --git a/front/app/translations/en.json b/front/app/translations/en.json index 07b7d4b02947..d72915882a4a 100644 --- a/front/app/translations/en.json +++ b/front/app/translations/en.json @@ -648,6 +648,7 @@ "app.components.form.controls.clickOnMapMultipleToAdd3": "Click on the map to draw. Then, drag on points to move them.", "app.components.form.controls.clickOnMapToAddOrType": "Click on the map or type an address below to add your answer.", "app.components.form.controls.confirm": "Confirm", + "app.components.form.controls.cosponsorsPlaceholder": "Start typing a name to search", "app.components.form.controls.minimumCoordinates2": "A minimum of {numPoints} map points is required.", "app.components.form.controls.notPublic1": "*This answer will only be shared with project managers, and not to the public.", "app.components.form.controls.selectAsManyAsYouLike": "*Select as many as you like", From f4342f13f81d0621d2bdf128cee4d3677756841c Mon Sep 17 00:00:00 2001 From: Adrien Dessy <adrien@citizenlab.co> Date: Tue, 17 Sep 2024 16:36:52 +0200 Subject: [PATCH 08/43] [TAN-2224] Add consponsors to the Idea model --- back/app/models/cosponsors_idea.rb | 26 ++++++++++ back/app/models/idea.rb | 4 +- back/app/models/user.rb | 2 + .../20240917181018_create_cosponsors_ideas.rb | 10 ++++ back/db/structure.sql | 48 ++++++++++++++++++- 5 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 back/app/models/cosponsors_idea.rb create mode 100644 back/db/migrate/20240917181018_create_cosponsors_ideas.rb diff --git a/back/app/models/cosponsors_idea.rb b/back/app/models/cosponsors_idea.rb new file mode 100644 index 000000000000..24088d6967a1 --- /dev/null +++ b/back/app/models/cosponsors_idea.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: cosponsors_ideas +# +# cosponsor_id :uuid +# idea_id :uuid +# +# Indexes +# +# index_cosponsors_ideas_on_cosponsor_id (cosponsor_id) +# index_cosponsors_ideas_on_idea_id (idea_id) +# +# Foreign Keys +# +# fk_rails_... (cosponsor_id => users.id) +# fk_rails_... (idea_id => ideas.id) +# +class CosponsorsIdea < ApplicationRecord + belongs_to :idea + belongs_to :cosponsor, class_name: 'User' + + validates :idea, :cosponsor, presence: true + validates :cosponsor_id, uniqueness: { scope: :idea_id } +end diff --git a/back/app/models/idea.rb b/back/app/models/idea.rb index d5b56ca5d6ec..26a266f58224 100644 --- a/back/app/models/idea.rb +++ b/back/app/models/idea.rb @@ -92,7 +92,9 @@ class Idea < ApplicationRecord has_many :baskets, through: :baskets_ideas has_many :text_images, as: :imageable, dependent: :destroy has_many :followers, as: :followable, dependent: :destroy - has_many :cosponsors, class_name: 'User' + + has_many :cosponsors_ideas, dependent: :destroy + has_many :cosponsors, through: :cosponsors_ideas has_many :idea_images, -> { order(:ordering) }, dependent: :destroy, inverse_of: :idea has_many :idea_files, -> { order(:ordering) }, dependent: :destroy, inverse_of: :idea diff --git a/back/app/models/user.rb b/back/app/models/user.rb index a0494e8419d4..946b983dd50b 100644 --- a/back/app/models/user.rb +++ b/back/app/models/user.rb @@ -145,6 +145,8 @@ def oldest_admin has_many :attended_events, through: :event_attendances, source: :event has_many :follows, -> { order(:followable_id) }, class_name: 'Follower', dependent: :destroy has_many :cosponsors_initiatives, dependent: :destroy + has_many :cosponsors_ideas, dependent: :destroy, foreign_key: :cosponsor_id + has_many :cosponsored_ideas, through: :cosponsors_ideas, source: :idea before_validation :sanitize_bio_multiloc, if: :bio_multiloc before_validation :complete_registration diff --git a/back/db/migrate/20240917181018_create_cosponsors_ideas.rb b/back/db/migrate/20240917181018_create_cosponsors_ideas.rb new file mode 100644 index 000000000000..900558af98fb --- /dev/null +++ b/back/db/migrate/20240917181018_create_cosponsors_ideas.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +class CreateCosponsorsIdeas < ActiveRecord::Migration[7.0] + def change + create_table :cosponsors_ideas, id: false do |t| + t.references :cosponsor, foreign_key: { to_table: :users }, type: :uuid, index: true + t.references :idea, foreign_key: true, type: :uuid, index: true + end + end +end diff --git a/back/db/structure.sql b/back/db/structure.sql index 1591807feeb7..8e2e99cd80c3 100644 --- a/back/db/structure.sql +++ b/back/db/structure.sql @@ -49,6 +49,7 @@ ALTER TABLE IF EXISTS ONLY public.baskets DROP CONSTRAINT IF EXISTS fk_rails_b3d ALTER TABLE IF EXISTS ONLY public.phases DROP CONSTRAINT IF EXISTS fk_rails_b0efe660f5; ALTER TABLE IF EXISTS ONLY public.analysis_tags DROP CONSTRAINT IF EXISTS fk_rails_afc2d02258; ALTER TABLE IF EXISTS ONLY public.maps_layers DROP CONSTRAINT IF EXISTS fk_rails_abbf8658b2; +ALTER TABLE IF EXISTS ONLY public.cosponsors_ideas DROP CONSTRAINT IF EXISTS fk_rails_ab6cd41bd4; ALTER TABLE IF EXISTS ONLY public.memberships DROP CONSTRAINT IF EXISTS fk_rails_aaf389f138; ALTER TABLE IF EXISTS ONLY public.analytics_fact_visits DROP CONSTRAINT IF EXISTS fk_rails_a9aa810ecf; ALTER TABLE IF EXISTS ONLY public.ideas DROP CONSTRAINT IF EXISTS fk_rails_a7a91f1df3; @@ -95,6 +96,7 @@ ALTER TABLE IF EXISTS ONLY public.idea_imports DROP CONSTRAINT IF EXISTS fk_rail ALTER TABLE IF EXISTS ONLY public.internal_comments DROP CONSTRAINT IF EXISTS fk_rails_617a7ea994; ALTER TABLE IF EXISTS ONLY public.analysis_taggings DROP CONSTRAINT IF EXISTS fk_rails_604cfbcd8d; ALTER TABLE IF EXISTS ONLY public.idea_imports DROP CONSTRAINT IF EXISTS fk_rails_5ea1f11fd5; +ALTER TABLE IF EXISTS ONLY public.cosponsors_ideas DROP CONSTRAINT IF EXISTS fk_rails_5d8bf90f09; ALTER TABLE IF EXISTS ONLY public.ideas DROP CONSTRAINT IF EXISTS fk_rails_5ac7668cd3; ALTER TABLE IF EXISTS ONLY public.cosponsors_initiatives DROP CONSTRAINT IF EXISTS fk_rails_5ac54ec4a5; ALTER TABLE IF EXISTS ONLY public.notifications DROP CONSTRAINT IF EXISTS fk_rails_575368d182; @@ -312,6 +314,8 @@ DROP INDEX IF EXISTS public.index_custom_field_options_on_custom_field_id; DROP INDEX IF EXISTS public.index_custom_field_option_images_on_custom_field_option_id; DROP INDEX IF EXISTS public.index_cosponsors_initiatives_on_user_id; DROP INDEX IF EXISTS public.index_cosponsors_initiatives_on_initiative_id; +DROP INDEX IF EXISTS public.index_cosponsors_ideas_on_idea_id; +DROP INDEX IF EXISTS public.index_cosponsors_ideas_on_cosponsor_id; DROP INDEX IF EXISTS public.index_content_builder_layouts_content_buidable_type_id_code; DROP INDEX IF EXISTS public.index_common_passwords_on_password; DROP INDEX IF EXISTS public.index_comments_on_rgt; @@ -569,6 +573,7 @@ DROP TABLE IF EXISTS public.custom_fields; DROP TABLE IF EXISTS public.custom_field_options; DROP TABLE IF EXISTS public.custom_field_option_images; DROP TABLE IF EXISTS public.cosponsors_initiatives; +DROP TABLE IF EXISTS public.cosponsors_ideas; DROP TABLE IF EXISTS public.content_builder_layouts; DROP TABLE IF EXISTS public.content_builder_layout_images; DROP TABLE IF EXISTS public.common_passwords; @@ -2138,6 +2143,16 @@ CREATE TABLE public.content_builder_layouts ( ); +-- +-- Name: cosponsors_ideas; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.cosponsors_ideas ( + cosponsor_id uuid, + idea_id uuid +); + + -- -- Name: cosponsors_initiatives; Type: TABLE; Schema: public; Owner: - -- @@ -4778,6 +4793,20 @@ CREATE INDEX index_common_passwords_on_password ON public.common_passwords USING CREATE UNIQUE INDEX index_content_builder_layouts_content_buidable_type_id_code ON public.content_builder_layouts USING btree (content_buildable_type, content_buildable_id, code); +-- +-- Name: index_cosponsors_ideas_on_cosponsor_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_cosponsors_ideas_on_cosponsor_id ON public.cosponsors_ideas USING btree (cosponsor_id); + + +-- +-- Name: index_cosponsors_ideas_on_idea_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_cosponsors_ideas_on_idea_id ON public.cosponsors_ideas USING btree (idea_id); + + -- -- Name: index_cosponsors_initiatives_on_initiative_id; Type: INDEX; Schema: public; Owner: - -- @@ -6330,6 +6359,14 @@ ALTER TABLE ONLY public.ideas ADD CONSTRAINT fk_rails_5ac7668cd3 FOREIGN KEY (project_id) REFERENCES public.projects(id); +-- +-- Name: cosponsors_ideas fk_rails_5d8bf90f09; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.cosponsors_ideas + ADD CONSTRAINT fk_rails_5d8bf90f09 FOREIGN KEY (idea_id) REFERENCES public.ideas(id); + + -- -- Name: idea_imports fk_rails_5ea1f11fd5; Type: FK CONSTRAINT; Schema: public; Owner: - -- @@ -6698,6 +6735,14 @@ ALTER TABLE ONLY public.memberships ADD CONSTRAINT fk_rails_aaf389f138 FOREIGN KEY (group_id) REFERENCES public.groups(id); +-- +-- Name: cosponsors_ideas fk_rails_ab6cd41bd4; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.cosponsors_ideas + ADD CONSTRAINT fk_rails_ab6cd41bd4 FOREIGN KEY (cosponsor_id) REFERENCES public.users(id); + + -- -- Name: maps_layers fk_rails_abbf8658b2; Type: FK CONSTRAINT; Schema: public; Owner: - -- @@ -7473,6 +7518,7 @@ INSERT INTO "schema_migrations" (version) VALUES ('20240814163522'), ('20240821135150'), ('20240826083227'), -('20240829185625'); +('20240829185625'), +('20240917181018'); From 9fd0b8e2bf17ff39d30de0361a6d3f6bbf13265e Mon Sep 17 00:00:00 2001 From: Iva <iva@citizenlab.co> Date: Tue, 17 Sep 2024 17:56:03 +0300 Subject: [PATCH 09/43] Add cosponsors to idea serializer --- back/app/serializers/web_api/v1/idea_serializer.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/back/app/serializers/web_api/v1/idea_serializer.rb b/back/app/serializers/web_api/v1/idea_serializer.rb index 55b3c7803cb3..31f45ab0c431 100644 --- a/back/app/serializers/web_api/v1/idea_serializer.rb +++ b/back/app/serializers/web_api/v1/idea_serializer.rb @@ -58,6 +58,7 @@ class WebApi::V1::IdeaSerializer < WebApi::V1::BaseSerializer has_many :idea_images, serializer: WebApi::V1::ImageSerializer has_many :phases has_many :ideas_phases + has_many :cosponsors, record_type: :user, serializer: WebApi::V1::UserSerializer belongs_to :author, record_type: :user, serializer: WebApi::V1::UserSerializer belongs_to :project From a77f77cc96d8f5478639e1f3f6fbdaef66805ddd Mon Sep 17 00:00:00 2001 From: Iva <iva@citizenlab.co> Date: Wed, 18 Sep 2024 16:20:37 +0300 Subject: [PATCH 10/43] Display names in mention area --- front/app/api/ideas/types.ts | 3 ++ front/app/api/users/useUsersByIds.ts | 29 +++++++++++++ .../Components/Controls/CosponsorsControl.tsx | 41 ++++++++++++------- .../app/components/FormBuilder/edit/index.tsx | 1 - front/app/components/FormBuilder/utils.tsx | 3 ++ .../IdeasWithoutFiltersSidebar/index.tsx | 1 + .../projects/project/inputForm/utils.tsx | 10 ++++- .../ReviewSection/IdeaEditor/IdeaForm.tsx | 1 + .../ReviewSection/IdeaEditor/index.tsx | 1 + .../IdeasEditPage/IdeasEditForm.tsx | 1 + front/app/containers/IdeasEditPage/utils.tsx | 8 ++++ .../IdeasNewIdeationForm/index.tsx | 1 + front/app/containers/IdeasNewPage/messages.ts | 4 ++ 13 files changed, 88 insertions(+), 16 deletions(-) create mode 100644 front/app/api/users/useUsersByIds.ts diff --git a/front/app/api/ideas/types.ts b/front/app/api/ideas/types.ts index 4a1d573a9f85..08efbaa92e64 100644 --- a/front/app/api/ideas/types.ts +++ b/front/app/api/ideas/types.ts @@ -131,6 +131,9 @@ export interface IIdeaData { idea_import?: { data: IRelationship | null; }; + cosponsors?: { + data: IRelationship | null; + }; }; } diff --git a/front/app/api/users/useUsersByIds.ts b/front/app/api/users/useUsersByIds.ts new file mode 100644 index 000000000000..6bec800a4657 --- /dev/null +++ b/front/app/api/users/useUsersByIds.ts @@ -0,0 +1,29 @@ +import { UseQueryOptions, useQueries } from '@tanstack/react-query'; + +import fetcher from 'utils/cl-react-query/fetcher'; + +import usersKeys from './keys'; +import { IUser } from './types'; + +type UsersWithIdsReturnType = UseQueryOptions<IUser>[]; + +export const fetchUser = (id: string) => { + return fetcher<IUser>({ + path: `/users/${id}`, + action: 'get', + }); +}; + +const useUsersWithIds = (userIds?: string[]) => { + const queries = userIds + ? userIds.map((userId) => ({ + queryKey: usersKeys.item({ id: userId }), + queryFn: () => fetchUser(userId), + })) + : []; + return useQueries<UsersWithIdsReturnType>({ + queries, + }); +}; + +export default useUsersWithIds; diff --git a/front/app/components/Form/Components/Controls/CosponsorsControl.tsx b/front/app/components/Form/Components/Controls/CosponsorsControl.tsx index bca9d4121c48..f359a333a988 100644 --- a/front/app/components/Form/Components/Controls/CosponsorsControl.tsx +++ b/front/app/components/Form/Components/Controls/CosponsorsControl.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { Box } from '@citizenlab/cl2-component-library'; import { @@ -11,19 +11,20 @@ import { withJsonFormsControlProps } from '@jsonforms/react'; import { WrappedComponentProps } from 'react-intl'; import { MentionItem } from 'react-mentions'; +import useUsersWithIds from 'api/users/useUsersByIds'; + import { FormLabel } from 'components/UI/FormComponents'; import MentionsTextArea from 'components/UI/MentionsTextArea'; import { useIntl } from 'utils/cl-intl'; import { getLabel, sanitizeForClassname } from 'utils/JSONFormUtils'; +import { getFullName } from 'utils/textUtils'; import ErrorDisplay from '../ErrorDisplay'; import { getSubtextElement } from './controlUtils'; import messages from './messages'; -const cosponsorships: any = []; - const CosponsorsControl = ({ uischema, schema, @@ -35,16 +36,28 @@ const CosponsorsControl = ({ visible, id, }: ControlProps & WrappedComponentProps) => { - const initialCosponsorsText = cosponsorships - ? cosponsorships.reduce( + const [initialRender, setInitialRender] = useState(true); + const results = useUsersWithIds(data); + + const [cosponsorsText, setCosponsorsText] = useState<string | null>(null); + + useEffect(() => { + const users = results.map((result) => result?.data); + if (initialRender) { + const initialCosponsorsText = users.reduce( (acc, cosponsorship) => - `${acc}@[${cosponsorship.name}](${cosponsorship.user_id}) `, + cosponsorship + ? `${acc}@[${getFullName(cosponsorship.data)}](${ + cosponsorship.data.id + }) ` + : '', '' - ) - : null; - const [cosponsorsText, setCosponsorsText] = useState<string | null>( - initialCosponsorsText - ); + ); + setCosponsorsText(initialCosponsorsText); + setInitialRender(false); + } + }, [initialRender, results]); + const { formatMessage } = useIntl(); const [didBlur, setDidBlur] = useState(false); @@ -64,17 +77,17 @@ const CosponsorsControl = ({ optional={!required} subtextValue={getSubtextElement(uischema.options?.description)} subtextSupportsHtml + htmlFor={sanitizeForClassname(id)} /> </Box> <MentionsTextArea - id="e2e-idea-form-cosponsors-input-field" + id={sanitizeForClassname(id)} name="cosponsor_ids" rows={1} trigger="" userReferenceType="id" padding="8px 8px 12px" - // value={data} onChange={(text: string) => { handleOnChangeInputField(text); }} @@ -84,8 +97,8 @@ const CosponsorsControl = ({ }} placeholder={formatMessage(messages.cosponsorsPlaceholder)} onBlur={() => setDidBlur(true)} - showUniqueUsers value={cosponsorsText} + showUniqueUsers /> <ErrorDisplay inputId={sanitizeForClassname(id)} diff --git a/front/app/components/FormBuilder/edit/index.tsx b/front/app/components/FormBuilder/edit/index.tsx index 930b53513fc0..93f2819ae78b 100644 --- a/front/app/components/FormBuilder/edit/index.tsx +++ b/front/app/components/FormBuilder/edit/index.tsx @@ -238,7 +238,6 @@ const FormEdit = ({ maximum: field.maximum?.toString() || '5', }), })); - console.log(finalResponseArray); await updateFormCustomFields( { diff --git a/front/app/components/FormBuilder/utils.tsx b/front/app/components/FormBuilder/utils.tsx index 568672ac5bc2..f33cdc21d8f0 100644 --- a/front/app/components/FormBuilder/utils.tsx +++ b/front/app/components/FormBuilder/utils.tsx @@ -202,6 +202,9 @@ const getBuiltInFieldStringKey = ( case 'topic_ids': translatedStringKey = messages.tags; break; + case 'cosponsor_ids': + translatedStringKey = messages.cosponsors; + break; case 'proposed_budget': translatedStringKey = messages.proposedBudget; break; diff --git a/front/app/components/IdeaCards/IdeasWithoutFiltersSidebar/index.tsx b/front/app/components/IdeaCards/IdeasWithoutFiltersSidebar/index.tsx index 8396d81d3476..0606cf8557b8 100644 --- a/front/app/components/IdeaCards/IdeasWithoutFiltersSidebar/index.tsx +++ b/front/app/components/IdeaCards/IdeasWithoutFiltersSidebar/index.tsx @@ -183,6 +183,7 @@ const IdeasWithoutFiltersSidebar = ({ locale ) : false; + const showViewButtons = !!(locationEnabled && showViewToggle); const showSearch = !(selectedView === 'map') && showSearchbar; diff --git a/front/app/containers/Admin/projects/project/inputForm/utils.tsx b/front/app/containers/Admin/projects/project/inputForm/utils.tsx index 8749d0b77f4d..f7ab9392fec7 100644 --- a/front/app/containers/Admin/projects/project/inputForm/utils.tsx +++ b/front/app/containers/Admin/projects/project/inputForm/utils.tsx @@ -22,6 +22,7 @@ export const ideationConfig: FormBuilderConfig = { 'point', 'line', 'polygon', + 'cosponsor_ids', ], displayBuiltInFields: true, builtInFields: [ @@ -58,7 +59,14 @@ export const proposalsConfig: FormBuilderConfig = { formSavedSuccessMessage: messages.successMessage, toolboxTitle: messages.customToolboxTitle, - toolboxFieldsToExclude: ['page', 'file_upload', 'point'], + toolboxFieldsToExclude: [ + 'page', + 'file_upload', + 'shapefile_upload', + 'point', + 'line', + 'polygon', + ], displayBuiltInFields: true, builtInFields: [ 'title_multiloc', diff --git a/front/app/containers/Admin/projects/project/inputImporter/ReviewSection/IdeaEditor/IdeaForm.tsx b/front/app/containers/Admin/projects/project/inputImporter/ReviewSection/IdeaEditor/IdeaForm.tsx index bc1a6f9b4556..ff34c4ec26f6 100644 --- a/front/app/containers/Admin/projects/project/inputImporter/ReviewSection/IdeaEditor/IdeaForm.tsx +++ b/front/app/containers/Admin/projects/project/inputImporter/ReviewSection/IdeaEditor/IdeaForm.tsx @@ -93,6 +93,7 @@ const NOT_SUPPORTED_SCOPES = new Set([ '#/properties/idea_images_attributes', '#/properties/idea_files_attributes', '#/properties/topic_ids', + '#/properties/cosponsor_ids', ]); const filterUiSchema = (uiSchema) => { diff --git a/front/app/containers/Admin/projects/project/inputImporter/ReviewSection/IdeaEditor/index.tsx b/front/app/containers/Admin/projects/project/inputImporter/ReviewSection/IdeaEditor/index.tsx index 1639448d816d..9fe4cb8bdc89 100644 --- a/front/app/containers/Admin/projects/project/inputImporter/ReviewSection/IdeaEditor/index.tsx +++ b/front/app/containers/Admin/projects/project/inputImporter/ReviewSection/IdeaEditor/index.tsx @@ -179,6 +179,7 @@ const IdeaEditor = ({ ideaId, setIdeaId }: Props) => { idea_files_attributes: _idea_files_attributes, idea_images_attributes: _idea_images_attributes, topic_ids: _topic_ideas, + cosponsor_ids: _cosponsor_ids, author_id: _author_id, ...supportedFormData } = ideaFormData; diff --git a/front/app/containers/IdeasEditPage/IdeasEditForm.tsx b/front/app/containers/IdeasEditPage/IdeasEditForm.tsx index e0e8a2d4b9b6..2649dc8a166c 100644 --- a/front/app/containers/IdeasEditPage/IdeasEditForm.tsx +++ b/front/app/containers/IdeasEditPage/IdeasEditForm.tsx @@ -45,6 +45,7 @@ interface FormValues { location_description?: string; location_point_geojson?: GeoJSON.Point; topic_ids?: string[]; + cosponsor_ids?: string[]; } interface Props { ideaId: string; diff --git a/front/app/containers/IdeasEditPage/utils.tsx b/front/app/containers/IdeasEditPage/utils.tsx index 171f72a89ccd..5a37ea7c50ad 100644 --- a/front/app/containers/IdeasEditPage/utils.tsx +++ b/front/app/containers/IdeasEditPage/utils.tsx @@ -51,6 +51,14 @@ export const getFormValues = ( prop, idea.data.relationships?.topics?.data.map((rel) => rel.id), ]; + } else if ( + prop === 'cosponsor_ids' && + Array.isArray(idea.data.relationships?.cosponsors?.data) + ) { + return [ + prop, + idea.data.relationships?.cosponsors?.data.map((rel) => rel.id), + ]; } else if ( prop === 'idea_images_attributes' && Array.isArray(idea.data.relationships?.idea_images?.data) diff --git a/front/app/containers/IdeasNewPage/IdeasNewIdeationForm/index.tsx b/front/app/containers/IdeasNewPage/IdeasNewIdeationForm/index.tsx index 10eb5d5888c6..35f00805df57 100644 --- a/front/app/containers/IdeasNewPage/IdeasNewIdeationForm/index.tsx +++ b/front/app/containers/IdeasNewPage/IdeasNewIdeationForm/index.tsx @@ -63,6 +63,7 @@ interface FormValues { location_description?: string; location_point_geojson?: GeoJSON.Point; topic_ids?: string[]; + cosponsor_ids?: string[]; publication_status?: IdeaPublicationStatus; } diff --git a/front/app/containers/IdeasNewPage/messages.ts b/front/app/containers/IdeasNewPage/messages.ts index f7519dee1a12..9f8c1f7f7bab 100644 --- a/front/app/containers/IdeasNewPage/messages.ts +++ b/front/app/containers/IdeasNewPage/messages.ts @@ -170,6 +170,10 @@ export default defineMessages({ id: 'app.containers.IdeasNewPage.ajv_error_option_topic_ids_minItems', defaultMessage: 'Please select at least one tag', }, + ajv_error_cosponsor_ids_required: { + id: 'app.containers.IdeasNewPage.ajv_error_cosponsor_ids_required', + defaultMessage: 'Please select at least one cosponsor', + }, ajv_error_proposed_budget_required: { id: 'app.containers.IdeasNewPage.ajv_error_proposed_budget_required', defaultMessage: 'Please enter a number', From bad8d4c6710b7b34a642a10aac337cf548dbc3e3 Mon Sep 17 00:00:00 2001 From: CircleCI <hello@citizenlab.co> Date: Wed, 18 Sep 2024 13:24:10 +0000 Subject: [PATCH 11/43] Translations updated by CI (extract-intl) --- front/app/translations/en.json | 1 + 1 file changed, 1 insertion(+) diff --git a/front/app/translations/en.json b/front/app/translations/en.json index d72915882a4a..c023ab348b4c 100644 --- a/front/app/translations/en.json +++ b/front/app/translations/en.json @@ -1235,6 +1235,7 @@ "app.containers.IdeasNewPage.ajv_error_contribution_body_multiloc_minLength": "The idea body must be more than {limit} characters long", "app.containers.IdeasNewPage.ajv_error_contribution_title_multiloc_maxLength": "The contribution title must be less than {limit} characters long", "app.containers.IdeasNewPage.ajv_error_contribution_title_multiloc_minLength1": "The contribution title must be more than {limit} characters long", + "app.containers.IdeasNewPage.ajv_error_cosponsor_ids_required": "Please select at least one cosponsor", "app.containers.IdeasNewPage.ajv_error_idea_body_multiloc_maxLength": "The idea description must be less than {limit} characters long", "app.containers.IdeasNewPage.ajv_error_idea_body_multiloc_minLength": "The idea description must be more than {limit} characters long", "app.containers.IdeasNewPage.ajv_error_idea_body_multiloc_required": "Please provide a description", From c6a3d3e33be87ea2103e2506d103e721ed212403 Mon Sep 17 00:00:00 2001 From: Koen Gremmelprez <koen.gremmelprez@gmail.com> Date: Wed, 18 Sep 2024 15:51:40 +0200 Subject: [PATCH 12/43] Rename references to ideas_cosponsors relationship to consponsorships --- back/app/models/idea.rb | 4 ++-- back/app/models/user.rb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/back/app/models/idea.rb b/back/app/models/idea.rb index 26a266f58224..d62c358f9310 100644 --- a/back/app/models/idea.rb +++ b/back/app/models/idea.rb @@ -93,8 +93,8 @@ class Idea < ApplicationRecord has_many :text_images, as: :imageable, dependent: :destroy has_many :followers, as: :followable, dependent: :destroy - has_many :cosponsors_ideas, dependent: :destroy - has_many :cosponsors, through: :cosponsors_ideas + has_many :cosposorships, dependent: :destroy + has_many :cosponsors, through: :cosposorships, source: :user has_many :idea_images, -> { order(:ordering) }, dependent: :destroy, inverse_of: :idea has_many :idea_files, -> { order(:ordering) }, dependent: :destroy, inverse_of: :idea diff --git a/back/app/models/user.rb b/back/app/models/user.rb index 946b983dd50b..ff2934d2add1 100644 --- a/back/app/models/user.rb +++ b/back/app/models/user.rb @@ -145,8 +145,8 @@ def oldest_admin has_many :attended_events, through: :event_attendances, source: :event has_many :follows, -> { order(:followable_id) }, class_name: 'Follower', dependent: :destroy has_many :cosponsors_initiatives, dependent: :destroy - has_many :cosponsors_ideas, dependent: :destroy, foreign_key: :cosponsor_id - has_many :cosponsored_ideas, through: :cosponsors_ideas, source: :idea + has_many :cosponsorships, dependent: :destroy, foreign_key: :cosponsor_id + has_many :cosponsored_ideas, through: :cosponsorships, source: :idea before_validation :sanitize_bio_multiloc, if: :bio_multiloc before_validation :complete_registration From 2d11d6305a58fbff58349484aff186ed1e67a962 Mon Sep 17 00:00:00 2001 From: Iva <iva@citizenlab.co> Date: Wed, 18 Sep 2024 17:03:11 +0300 Subject: [PATCH 13/43] Add migration --- back/app/models/cosponsorship.rb | 30 +++++++++++++++++++ .../20240917181018_create_cosponsorships.rb | 13 ++++++++ 2 files changed, 43 insertions(+) create mode 100644 back/app/models/cosponsorship.rb create mode 100644 back/db/migrate/20240917181018_create_cosponsorships.rb diff --git a/back/app/models/cosponsorship.rb b/back/app/models/cosponsorship.rb new file mode 100644 index 000000000000..5c4c0d1bbf66 --- /dev/null +++ b/back/app/models/cosponsorship.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +# == Schema Information +# +# Table name: cosponsors_ideas +# +# cosponsor_id :uuid +# idea_id :uuid +# +# Indexes +# +# index_cosponsors_ideas_on_cosponsor_id (cosponsor_id) +# index_cosponsors_ideas_on_idea_id (idea_id) +# +# Foreign Keys +# +# fk_rails_... (cosponsor_id => users.id) +# fk_rails_... (idea_id => ideas.id) +# +class Cosponsorship < ApplicationRecord + STATUSES = %w[pending accepted].freeze + + belongs_to :user + belongs_to :idea + + has_many :notifications, dependent: :nullify + + validates :user, :idea, presence: true + validates :status, inclusion: { in: STATUSES } +end diff --git a/back/db/migrate/20240917181018_create_cosponsorships.rb b/back/db/migrate/20240917181018_create_cosponsorships.rb new file mode 100644 index 000000000000..70357494cd61 --- /dev/null +++ b/back/db/migrate/20240917181018_create_cosponsorships.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class CreateCosponsorships < ActiveRecord::Migration[7.0] + def change + create_table :cosponsorships, id: :uuid do |t| + t.string :status, default: 'pending', null: false + t.references :user, foreign_key: true, type: :uuid, index: true, null: false + t.references :idea, foreign_key: true, type: :uuid, index: true, null: false + + t.timestamps + end + end +end From fbe77a73a1173920821e595132e9bf198fb50881 Mon Sep 17 00:00:00 2001 From: Iva <iva@citizenlab.co> Date: Wed, 18 Sep 2024 17:50:13 +0300 Subject: [PATCH 14/43] Add feature flag logic --- back/app/models/idea.rb | 4 ++-- back/app/models/user.rb | 4 ++-- .../20240917181018_create_cosponsors_ideas.rb | 10 -------- front/app/api/app_configuration/types.ts | 1 + .../FormBuilderToolbox/BuiltInFields.tsx | 24 ++++++++++++------- .../FormBuilderToolbox/ToolboxItem.tsx | 3 ++- 6 files changed, 22 insertions(+), 24 deletions(-) delete mode 100644 back/db/migrate/20240917181018_create_cosponsors_ideas.rb diff --git a/back/app/models/idea.rb b/back/app/models/idea.rb index 111259a47a05..d5ad692d07e2 100644 --- a/back/app/models/idea.rb +++ b/back/app/models/idea.rb @@ -93,8 +93,8 @@ class Idea < ApplicationRecord has_many :text_images, as: :imageable, dependent: :destroy has_many :followers, as: :followable, dependent: :destroy - has_many :cosposorships, dependent: :destroy - has_many :cosponsors, through: :cosposorships, source: :user + has_many :cosponsorships, dependent: :destroy + has_many :cosponsors, through: :cosponsorships, source: :user has_many :idea_images, -> { order(:ordering) }, dependent: :destroy, inverse_of: :idea has_many :idea_files, -> { order(:ordering) }, dependent: :destroy, inverse_of: :idea diff --git a/back/app/models/user.rb b/back/app/models/user.rb index ff2934d2add1..54ebf65148c6 100644 --- a/back/app/models/user.rb +++ b/back/app/models/user.rb @@ -145,8 +145,8 @@ def oldest_admin has_many :attended_events, through: :event_attendances, source: :event has_many :follows, -> { order(:followable_id) }, class_name: 'Follower', dependent: :destroy has_many :cosponsors_initiatives, dependent: :destroy - has_many :cosponsorships, dependent: :destroy, foreign_key: :cosponsor_id - has_many :cosponsored_ideas, through: :cosponsorships, source: :idea + # has_many :cosponsorships, dependent: :destroy, foreign_key: :cosponsor_id + # has_many :cosponsored_ideas, through: :cosponsorships, source: :idea before_validation :sanitize_bio_multiloc, if: :bio_multiloc before_validation :complete_registration diff --git a/back/db/migrate/20240917181018_create_cosponsors_ideas.rb b/back/db/migrate/20240917181018_create_cosponsors_ideas.rb deleted file mode 100644 index 900558af98fb..000000000000 --- a/back/db/migrate/20240917181018_create_cosponsors_ideas.rb +++ /dev/null @@ -1,10 +0,0 @@ -# frozen_string_literal: true - -class CreateCosponsorsIdeas < ActiveRecord::Migration[7.0] - def change - create_table :cosponsors_ideas, id: false do |t| - t.references :cosponsor, foreign_key: { to_table: :users }, type: :uuid, index: true - t.references :idea, foreign_key: true, type: :uuid, index: true - end - end -end diff --git a/front/app/api/app_configuration/types.ts b/front/app/api/app_configuration/types.ts index 4896a491534e..03a2138d0908 100644 --- a/front/app/api/app_configuration/types.ts +++ b/front/app/api/app_configuration/types.ts @@ -240,6 +240,7 @@ export interface IAppConfigurationSettings { proposals_participation_method?: AppConfigurationFeature; fake_sso?: AppConfigurationFeature; prescreening?: AppConfigurationFeature; + input_cosponsorship?: AppConfigurationFeature; } export type TAppConfigurationSettingCore = keyof IAppConfigurationSettingsCore; diff --git a/front/app/components/FormBuilder/components/FormBuilderToolbox/BuiltInFields.tsx b/front/app/components/FormBuilder/components/FormBuilderToolbox/BuiltInFields.tsx index eac1eb30a45a..22814310dd25 100644 --- a/front/app/components/FormBuilder/components/FormBuilderToolbox/BuiltInFields.tsx +++ b/front/app/components/FormBuilder/components/FormBuilderToolbox/BuiltInFields.tsx @@ -15,6 +15,7 @@ import { FormattedMessage, useIntl } from 'utils/cl-intl'; import messages from '../messages'; import ToolboxItem from './ToolboxItem'; +import useFeatureFlag from 'hooks/useFeatureFlag'; interface BuiltInFieldsProps { move: (indexA: number, indexB: number) => void; @@ -22,6 +23,7 @@ interface BuiltInFieldsProps { } const BuiltInFields = ({ move, builderConfig }: BuiltInFieldsProps) => { + const cosponsorsEnabled = useFeatureFlag({ name: 'input_cosponsorship' }); const { watch, trigger, setValue } = useFormContext(); const { formatMessage } = useIntl(); const formCustomFields: IFlatCustomField[] = watch('customFields'); @@ -101,15 +103,19 @@ const BuiltInFields = ({ move, builderConfig }: BuiltInFieldsProps) => { data-cy="e2e-tags-item" /> )} - <ToolboxItem - icon="volunteer" - label={formatMessage(messages.cosponsors)} - onClick={() => enableField('cosponsor_ids')} - data-cy="e2e-cosponsors-field" - fieldsToExclude={builderConfig.toolboxFieldsToExclude} - inputType="cosponsor_ids" - disabledTooltipMessage={messages.disabledBuiltInFieldTooltip} - /> + {builderConfig.builtInFields.includes('cosponsor_ids') && + cosponsorsEnabled && ( + <ToolboxItem + icon="volunteer" + label={formatMessage(messages.cosponsors)} + onClick={() => enableField('cosponsor_ids')} + data-cy="e2e-cosponsors-field" + fieldsToExclude={builderConfig.toolboxFieldsToExclude} + inputType="cosponsor_ids" + disabled={!enabledBuiltInFieldKeys.includes('cosponsor_ids')} + disabledTooltipMessage={messages.disabledBuiltInFieldTooltip} + /> + )} </Box> ); }; diff --git a/front/app/components/FormBuilder/components/FormBuilderToolbox/ToolboxItem.tsx b/front/app/components/FormBuilder/components/FormBuilderToolbox/ToolboxItem.tsx index 5b24ee2f55d2..6f5f5ab1c5ef 100644 --- a/front/app/components/FormBuilder/components/FormBuilderToolbox/ToolboxItem.tsx +++ b/front/app/components/FormBuilder/components/FormBuilderToolbox/ToolboxItem.tsx @@ -31,6 +31,7 @@ interface Props { const AddIcon = styled(Icon).attrs({ name: 'plus' })` margin-left: auto; + margin-right: 12px; fill: ${colors.textSecondary}; margin-right: 0; `; @@ -92,7 +93,7 @@ const ToolboxItem = ({ > <StyledBox display="flex" - pl="8px" + p="18px" onClick={disabled ? () => {} : onClick} width="100%" m="0px" From 6f94519905de6f8514ce64376f34845b825eacad Mon Sep 17 00:00:00 2001 From: Iva <iva@citizenlab.co> Date: Wed, 18 Sep 2024 17:57:02 +0300 Subject: [PATCH 15/43] Execute migration --- back/app/models/user.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/back/app/models/user.rb b/back/app/models/user.rb index 54ebf65148c6..ff2934d2add1 100644 --- a/back/app/models/user.rb +++ b/back/app/models/user.rb @@ -145,8 +145,8 @@ def oldest_admin has_many :attended_events, through: :event_attendances, source: :event has_many :follows, -> { order(:followable_id) }, class_name: 'Follower', dependent: :destroy has_many :cosponsors_initiatives, dependent: :destroy - # has_many :cosponsorships, dependent: :destroy, foreign_key: :cosponsor_id - # has_many :cosponsored_ideas, through: :cosponsorships, source: :idea + has_many :cosponsorships, dependent: :destroy, foreign_key: :cosponsor_id + has_many :cosponsored_ideas, through: :cosponsorships, source: :idea before_validation :sanitize_bio_multiloc, if: :bio_multiloc before_validation :complete_registration From b149889b919f8b98ca29e0e85436298c086defad Mon Sep 17 00:00:00 2001 From: Iva <iva@citizenlab.co> Date: Wed, 18 Sep 2024 18:51:12 +0300 Subject: [PATCH 16/43] Fix migration --- back/app/models/cosponsorship.rb | 16 +++--- back/db/structure.sql | 87 ++++++++++++++++++-------------- 2 files changed, 60 insertions(+), 43 deletions(-) diff --git a/back/app/models/cosponsorship.rb b/back/app/models/cosponsorship.rb index 5c4c0d1bbf66..0221b29ffe94 100644 --- a/back/app/models/cosponsorship.rb +++ b/back/app/models/cosponsorship.rb @@ -2,20 +2,24 @@ # == Schema Information # -# Table name: cosponsors_ideas +# Table name: cosponsorships # -# cosponsor_id :uuid -# idea_id :uuid +# id :uuid not null, primary key +# status :string default("pending"), not null +# user_id :uuid not null +# idea_id :uuid not null +# created_at :datetime not null +# updated_at :datetime not null # # Indexes # -# index_cosponsors_ideas_on_cosponsor_id (cosponsor_id) -# index_cosponsors_ideas_on_idea_id (idea_id) +# index_cosponsorships_on_idea_id (idea_id) +# index_cosponsorships_on_user_id (user_id) # # Foreign Keys # -# fk_rails_... (cosponsor_id => users.id) # fk_rails_... (idea_id => ideas.id) +# fk_rails_... (user_id => users.id) # class Cosponsorship < ApplicationRecord STATUSES = %w[pending accepted].freeze diff --git a/back/db/structure.sql b/back/db/structure.sql index 2401fa882ff5..41bf517a1122 100644 --- a/back/db/structure.sql +++ b/back/db/structure.sql @@ -13,6 +13,7 @@ ALTER TABLE IF EXISTS ONLY public.ideas_topics DROP CONSTRAINT IF EXISTS fk_rail ALTER TABLE IF EXISTS ONLY public.ideas_topics DROP CONSTRAINT IF EXISTS fk_rails_fd874ecf4b; ALTER TABLE IF EXISTS ONLY public.events_attendances DROP CONSTRAINT IF EXISTS fk_rails_fba307ba3b; ALTER TABLE IF EXISTS ONLY public.comments DROP CONSTRAINT IF EXISTS fk_rails_f44b1e3c8a; +ALTER TABLE IF EXISTS ONLY public.cosponsorships DROP CONSTRAINT IF EXISTS fk_rails_f32533b783; ALTER TABLE IF EXISTS ONLY public.report_builder_published_graph_data_units DROP CONSTRAINT IF EXISTS fk_rails_f21a19c203; ALTER TABLE IF EXISTS ONLY public.idea_files DROP CONSTRAINT IF EXISTS fk_rails_efb12f53ad; ALTER TABLE IF EXISTS ONLY public.static_pages_topics DROP CONSTRAINT IF EXISTS fk_rails_edc8786515; @@ -49,7 +50,6 @@ ALTER TABLE IF EXISTS ONLY public.baskets DROP CONSTRAINT IF EXISTS fk_rails_b3d ALTER TABLE IF EXISTS ONLY public.phases DROP CONSTRAINT IF EXISTS fk_rails_b0efe660f5; ALTER TABLE IF EXISTS ONLY public.analysis_tags DROP CONSTRAINT IF EXISTS fk_rails_afc2d02258; ALTER TABLE IF EXISTS ONLY public.maps_layers DROP CONSTRAINT IF EXISTS fk_rails_abbf8658b2; -ALTER TABLE IF EXISTS ONLY public.cosponsors_ideas DROP CONSTRAINT IF EXISTS fk_rails_ab6cd41bd4; ALTER TABLE IF EXISTS ONLY public.memberships DROP CONSTRAINT IF EXISTS fk_rails_aaf389f138; ALTER TABLE IF EXISTS ONLY public.analytics_fact_visits DROP CONSTRAINT IF EXISTS fk_rails_a9aa810ecf; ALTER TABLE IF EXISTS ONLY public.ideas DROP CONSTRAINT IF EXISTS fk_rails_a7a91f1df3; @@ -96,7 +96,6 @@ ALTER TABLE IF EXISTS ONLY public.idea_imports DROP CONSTRAINT IF EXISTS fk_rail ALTER TABLE IF EXISTS ONLY public.internal_comments DROP CONSTRAINT IF EXISTS fk_rails_617a7ea994; ALTER TABLE IF EXISTS ONLY public.analysis_taggings DROP CONSTRAINT IF EXISTS fk_rails_604cfbcd8d; ALTER TABLE IF EXISTS ONLY public.idea_imports DROP CONSTRAINT IF EXISTS fk_rails_5ea1f11fd5; -ALTER TABLE IF EXISTS ONLY public.cosponsors_ideas DROP CONSTRAINT IF EXISTS fk_rails_5d8bf90f09; ALTER TABLE IF EXISTS ONLY public.ideas DROP CONSTRAINT IF EXISTS fk_rails_5ac7668cd3; ALTER TABLE IF EXISTS ONLY public.cosponsors_initiatives DROP CONSTRAINT IF EXISTS fk_rails_5ac54ec4a5; ALTER TABLE IF EXISTS ONLY public.notifications DROP CONSTRAINT IF EXISTS fk_rails_575368d182; @@ -116,6 +115,7 @@ ALTER TABLE IF EXISTS ONLY public.custom_field_option_images DROP CONSTRAINT IF ALTER TABLE IF EXISTS ONLY public.nav_bar_items DROP CONSTRAINT IF EXISTS fk_rails_34143a680f; ALTER TABLE IF EXISTS ONLY public.volunteering_volunteers DROP CONSTRAINT IF EXISTS fk_rails_33a154a9ba; ALTER TABLE IF EXISTS ONLY public.phase_files DROP CONSTRAINT IF EXISTS fk_rails_33852a9a71; +ALTER TABLE IF EXISTS ONLY public.cosponsorships DROP CONSTRAINT IF EXISTS fk_rails_2d026b99a2; ALTER TABLE IF EXISTS ONLY public.analysis_analyses DROP CONSTRAINT IF EXISTS fk_rails_2a92a64a56; ALTER TABLE IF EXISTS ONLY public.events_attendances DROP CONSTRAINT IF EXISTS fk_rails_29ccdf5b04; ALTER TABLE IF EXISTS ONLY public.areas_static_pages DROP CONSTRAINT IF EXISTS fk_rails_231f268568; @@ -312,10 +312,10 @@ DROP INDEX IF EXISTS public.index_custom_fields_on_resource_type_and_resource_id DROP INDEX IF EXISTS public.index_custom_field_options_on_custom_field_id_and_key; DROP INDEX IF EXISTS public.index_custom_field_options_on_custom_field_id; DROP INDEX IF EXISTS public.index_custom_field_option_images_on_custom_field_option_id; +DROP INDEX IF EXISTS public.index_cosponsorships_on_user_id; +DROP INDEX IF EXISTS public.index_cosponsorships_on_idea_id; DROP INDEX IF EXISTS public.index_cosponsors_initiatives_on_user_id; DROP INDEX IF EXISTS public.index_cosponsors_initiatives_on_initiative_id; -DROP INDEX IF EXISTS public.index_cosponsors_ideas_on_idea_id; -DROP INDEX IF EXISTS public.index_cosponsors_ideas_on_cosponsor_id; DROP INDEX IF EXISTS public.index_content_builder_layouts_content_buidable_type_id_code; DROP INDEX IF EXISTS public.index_common_passwords_on_password; DROP INDEX IF EXISTS public.index_comments_on_rgt; @@ -471,6 +471,7 @@ ALTER TABLE IF EXISTS ONLY public.custom_forms DROP CONSTRAINT IF EXISTS custom_ ALTER TABLE IF EXISTS ONLY public.custom_fields DROP CONSTRAINT IF EXISTS custom_fields_pkey; ALTER TABLE IF EXISTS ONLY public.custom_field_options DROP CONSTRAINT IF EXISTS custom_field_options_pkey; ALTER TABLE IF EXISTS ONLY public.custom_field_option_images DROP CONSTRAINT IF EXISTS custom_field_option_images_pkey; +ALTER TABLE IF EXISTS ONLY public.cosponsorships DROP CONSTRAINT IF EXISTS cosponsorships_pkey; ALTER TABLE IF EXISTS ONLY public.cosponsors_initiatives DROP CONSTRAINT IF EXISTS cosponsors_initiatives_pkey; ALTER TABLE IF EXISTS ONLY public.content_builder_layouts DROP CONSTRAINT IF EXISTS content_builder_layouts_pkey; ALTER TABLE IF EXISTS ONLY public.content_builder_layout_images DROP CONSTRAINT IF EXISTS content_builder_layout_images_pkey; @@ -572,8 +573,8 @@ DROP TABLE IF EXISTS public.custom_forms; DROP TABLE IF EXISTS public.custom_fields; DROP TABLE IF EXISTS public.custom_field_options; DROP TABLE IF EXISTS public.custom_field_option_images; +DROP TABLE IF EXISTS public.cosponsorships; DROP TABLE IF EXISTS public.cosponsors_initiatives; -DROP TABLE IF EXISTS public.cosponsors_ideas; DROP TABLE IF EXISTS public.content_builder_layouts; DROP TABLE IF EXISTS public.content_builder_layout_images; DROP TABLE IF EXISTS public.common_passwords; @@ -2144,24 +2145,28 @@ CREATE TABLE public.content_builder_layouts ( -- --- Name: cosponsors_ideas; Type: TABLE; Schema: public; Owner: - +-- Name: cosponsors_initiatives; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.cosponsors_ideas ( - cosponsor_id uuid, - idea_id uuid +CREATE TABLE public.cosponsors_initiatives ( + id uuid DEFAULT shared_extensions.gen_random_uuid() NOT NULL, + status character varying DEFAULT 'pending'::character varying NOT NULL, + user_id uuid NOT NULL, + initiative_id uuid NOT NULL, + created_at timestamp(6) without time zone NOT NULL, + updated_at timestamp(6) without time zone NOT NULL ); -- --- Name: cosponsors_initiatives; Type: TABLE; Schema: public; Owner: - +-- Name: cosponsorships; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE public.cosponsors_initiatives ( - id uuid DEFAULT shared_extensions.gen_random_uuid() NOT NULL, +CREATE TABLE public.cosponsorships ( + id uuid DEFAULT gen_random_uuid() NOT NULL, status character varying DEFAULT 'pending'::character varying NOT NULL, user_id uuid NOT NULL, - initiative_id uuid NOT NULL, + idea_id uuid NOT NULL, created_at timestamp(6) without time zone NOT NULL, updated_at timestamp(6) without time zone NOT NULL ); @@ -3621,6 +3626,14 @@ ALTER TABLE ONLY public.cosponsors_initiatives ADD CONSTRAINT cosponsors_initiatives_pkey PRIMARY KEY (id); +-- +-- Name: cosponsorships cosponsorships_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.cosponsorships + ADD CONSTRAINT cosponsorships_pkey PRIMARY KEY (id); + + -- -- Name: custom_field_option_images custom_field_option_images_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- @@ -4795,31 +4808,31 @@ CREATE UNIQUE INDEX index_content_builder_layouts_content_buidable_type_id_code -- --- Name: index_cosponsors_ideas_on_cosponsor_id; Type: INDEX; Schema: public; Owner: - +-- Name: index_cosponsors_initiatives_on_initiative_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_cosponsors_ideas_on_cosponsor_id ON public.cosponsors_ideas USING btree (cosponsor_id); +CREATE INDEX index_cosponsors_initiatives_on_initiative_id ON public.cosponsors_initiatives USING btree (initiative_id); -- --- Name: index_cosponsors_ideas_on_idea_id; Type: INDEX; Schema: public; Owner: - +-- Name: index_cosponsors_initiatives_on_user_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_cosponsors_ideas_on_idea_id ON public.cosponsors_ideas USING btree (idea_id); +CREATE INDEX index_cosponsors_initiatives_on_user_id ON public.cosponsors_initiatives USING btree (user_id); -- --- Name: index_cosponsors_initiatives_on_initiative_id; Type: INDEX; Schema: public; Owner: - +-- Name: index_cosponsorships_on_idea_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_cosponsors_initiatives_on_initiative_id ON public.cosponsors_initiatives USING btree (initiative_id); +CREATE INDEX index_cosponsorships_on_idea_id ON public.cosponsorships USING btree (idea_id); -- --- Name: index_cosponsors_initiatives_on_user_id; Type: INDEX; Schema: public; Owner: - +-- Name: index_cosponsorships_on_user_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_cosponsors_initiatives_on_user_id ON public.cosponsors_initiatives USING btree (user_id); +CREATE INDEX index_cosponsorships_on_user_id ON public.cosponsorships USING btree (user_id); -- @@ -6208,6 +6221,14 @@ ALTER TABLE ONLY public.analysis_analyses ADD CONSTRAINT fk_rails_2a92a64a56 FOREIGN KEY (phase_id) REFERENCES public.phases(id); +-- +-- Name: cosponsorships fk_rails_2d026b99a2; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.cosponsorships + ADD CONSTRAINT fk_rails_2d026b99a2 FOREIGN KEY (idea_id) REFERENCES public.ideas(id); + + -- -- Name: phase_files fk_rails_33852a9a71; Type: FK CONSTRAINT; Schema: public; Owner: - -- @@ -6360,14 +6381,6 @@ ALTER TABLE ONLY public.ideas ADD CONSTRAINT fk_rails_5ac7668cd3 FOREIGN KEY (project_id) REFERENCES public.projects(id); --- --- Name: cosponsors_ideas fk_rails_5d8bf90f09; Type: FK CONSTRAINT; Schema: public; Owner: - --- - -ALTER TABLE ONLY public.cosponsors_ideas - ADD CONSTRAINT fk_rails_5d8bf90f09 FOREIGN KEY (idea_id) REFERENCES public.ideas(id); - - -- -- Name: idea_imports fk_rails_5ea1f11fd5; Type: FK CONSTRAINT; Schema: public; Owner: - -- @@ -6736,14 +6749,6 @@ ALTER TABLE ONLY public.memberships ADD CONSTRAINT fk_rails_aaf389f138 FOREIGN KEY (group_id) REFERENCES public.groups(id); --- --- Name: cosponsors_ideas fk_rails_ab6cd41bd4; Type: FK CONSTRAINT; Schema: public; Owner: - --- - -ALTER TABLE ONLY public.cosponsors_ideas - ADD CONSTRAINT fk_rails_ab6cd41bd4 FOREIGN KEY (cosponsor_id) REFERENCES public.users(id); - - -- -- Name: maps_layers fk_rails_abbf8658b2; Type: FK CONSTRAINT; Schema: public; Owner: - -- @@ -7032,6 +7037,14 @@ ALTER TABLE ONLY public.report_builder_published_graph_data_units ADD CONSTRAINT fk_rails_f21a19c203 FOREIGN KEY (report_id) REFERENCES public.report_builder_reports(id); +-- +-- Name: cosponsorships fk_rails_f32533b783; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.cosponsorships + ADD CONSTRAINT fk_rails_f32533b783 FOREIGN KEY (user_id) REFERENCES public.users(id); + + -- -- Name: comments fk_rails_f44b1e3c8a; Type: FK CONSTRAINT; Schema: public; Owner: - -- From c68c5ab6e9583ecc598d2391fb07fed209e92be5 Mon Sep 17 00:00:00 2001 From: Iva <iva@citizenlab.co> Date: Thu, 19 Sep 2024 11:22:18 +0300 Subject: [PATCH 17/43] Fix cosponsor control --- .../web_api/v1/ideas_controller.rb | 2 +- .../Components/Controls/CosponsorsControl.tsx | 57 ++++++++++--------- 2 files changed, 32 insertions(+), 27 deletions(-) diff --git a/back/app/controllers/web_api/v1/ideas_controller.rb b/back/app/controllers/web_api/v1/ideas_controller.rb index 4f2380a21146..2e93111bd61f 100644 --- a/back/app/controllers/web_api/v1/ideas_controller.rb +++ b/back/app/controllers/web_api/v1/ideas_controller.rb @@ -235,7 +235,7 @@ def update render json: WebApi::V1::IdeaSerializer.new( input.reload, params: jsonapi_serializer_params, - include: %i[author topics user_reaction idea_images] + include: %i[author topics user_reaction idea_images cosponsors] ).serializable_hash, status: :ok else render json: { errors: input.errors.details }, status: :unprocessable_entity diff --git a/front/app/components/Form/Components/Controls/CosponsorsControl.tsx b/front/app/components/Form/Components/Controls/CosponsorsControl.tsx index f359a333a988..8cd4dca49faa 100644 --- a/front/app/components/Form/Components/Controls/CosponsorsControl.tsx +++ b/front/app/components/Form/Components/Controls/CosponsorsControl.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { useState } from 'react'; import { Box } from '@citizenlab/cl2-component-library'; import { @@ -24,39 +24,30 @@ import ErrorDisplay from '../ErrorDisplay'; import { getSubtextElement } from './controlUtils'; import messages from './messages'; +import { IUser } from 'api/users/types'; -const CosponsorsControl = ({ +const CosponsorsControlInner = ({ uischema, schema, - data, handleChange, path, errors, required, visible, id, -}: ControlProps & WrappedComponentProps) => { - const [initialRender, setInitialRender] = useState(true); - const results = useUsersWithIds(data); - - const [cosponsorsText, setCosponsorsText] = useState<string | null>(null); - - useEffect(() => { - const users = results.map((result) => result?.data); - if (initialRender) { - const initialCosponsorsText = users.reduce( - (acc, cosponsorship) => - cosponsorship - ? `${acc}@[${getFullName(cosponsorship.data)}](${ - cosponsorship.data.id - }) ` - : '', - '' - ); - setCosponsorsText(initialCosponsorsText); - setInitialRender(false); - } - }, [initialRender, results]); + users, +}: ControlProps & WrappedComponentProps & { users: IUser[] }) => { + const initialCosponsorsText = users.reduce( + (acc, cosponsor) => + `${acc}@[${getFullName(cosponsor?.data)}](${cosponsor?.data.id}) `, + '' + ); + + const [cosponsorsText, setCosponsorsText] = useState<string | null>( + initialCosponsorsText + ); + + console.log({ cosponsorsText }); const { formatMessage } = useIntl(); const [didBlur, setDidBlur] = useState(false); @@ -110,7 +101,21 @@ const CosponsorsControl = ({ ); }; -export default withJsonFormsControlProps(CosponsorsControl); +// Wrapping the control in a component that fetches the users with the given ids +// to make sure their names display correctly in the mentions text area +const CosponsorsControlOuter = ( + props: ControlProps & WrappedComponentProps +) => { + const results = useUsersWithIds(props.data); + const users = results.map((result) => result.data); + + if (results.some((result) => !result.data)) { + return null; + } + return <CosponsorsControlInner {...props} users={users as IUser[]} />; +}; + +export default withJsonFormsControlProps(CosponsorsControlOuter); export const cosponsorsControlTester: RankedTester = rankWith( 1000, From cbad8825e8b3877c88523a53f6fd81b517602409 Mon Sep 17 00:00:00 2001 From: Iva <iva@citizenlab.co> Date: Thu, 19 Sep 2024 13:06:58 +0300 Subject: [PATCH 18/43] Add endpoint for co-sponsorships --- .../web_api/v1/cosponsorships_controller.rb | 23 +++++++++++++++++++ .../web_api/v1/ideas_controller.rb | 2 +- back/app/policies/cosponsorship_policy.rb | 20 ++++++++++++++++ .../web_api/v1/cosponsorship_serializer.rb | 9 ++++++++ back/config/routes.rb | 2 ++ .../Components/Controls/CosponsorsControl.tsx | 2 -- 6 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 back/app/controllers/web_api/v1/cosponsorships_controller.rb create mode 100644 back/app/policies/cosponsorship_policy.rb create mode 100644 back/app/serializers/web_api/v1/cosponsorship_serializer.rb diff --git a/back/app/controllers/web_api/v1/cosponsorships_controller.rb b/back/app/controllers/web_api/v1/cosponsorships_controller.rb new file mode 100644 index 000000000000..d00deb53119d --- /dev/null +++ b/back/app/controllers/web_api/v1/cosponsorships_controller.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +class WebApi::V1::CosponsorshipsController < ApplicationController + before_action :set_cosponsorship, except: %i[index] + skip_before_action :authenticate_user, only: %i[index] + + def index + cosponsorships = policy_scope(Cosponsorship) + paginated_cosponsorships = paginate cosponsorships + render json: linked_json(paginated_cosponsorships, WebApi::V1::CosponsorshipSerializer, params: jsonapi_serializer_params) + end + + def accept_cosponsorship + + end + + private + + def set_topic + @cosponsorship = Cosponsorship.find(params[:id]) + authorize @cosponsorship + end +end diff --git a/back/app/controllers/web_api/v1/ideas_controller.rb b/back/app/controllers/web_api/v1/ideas_controller.rb index 2e93111bd61f..3fd450412b6b 100644 --- a/back/app/controllers/web_api/v1/ideas_controller.rb +++ b/back/app/controllers/web_api/v1/ideas_controller.rb @@ -396,7 +396,7 @@ def idea_status_not_allowed?(input) end def serialization_options_for(ideas) - include = %i[author idea_images ideas_phases] + include = %i[author idea_images ideas_phases cosponsors] if current_user # I have no idea why but the trending query part # breaks if you don't fetch the ids in this way. diff --git a/back/app/policies/cosponsorship_policy.rb b/back/app/policies/cosponsorship_policy.rb new file mode 100644 index 000000000000..baabe6e46e67 --- /dev/null +++ b/back/app/policies/cosponsorship_policy.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +class CosponsorshipPolicy < ApplicationPolicy + class Scope + attr_reader :user, :scope + + def initialize(user, scope) + @user = user + @scope = scope + end + + def resolve + scope.all + end + + def accept_cosponsorship? + user.id == record.user_id + end + end +end \ No newline at end of file diff --git a/back/app/serializers/web_api/v1/cosponsorship_serializer.rb b/back/app/serializers/web_api/v1/cosponsorship_serializer.rb new file mode 100644 index 000000000000..4436cc2168d5 --- /dev/null +++ b/back/app/serializers/web_api/v1/cosponsorship_serializer.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +class WebApi::V1::CosponsorshipSerializer < WebApi::V1::BaseSerializer + attributes :status + + belongs_to :idea + belongs_to :user + +end \ No newline at end of file diff --git a/back/config/routes.rb b/back/config/routes.rb index 72a655aec030..45f9fe0f96e6 100644 --- a/back/config/routes.rb +++ b/back/config/routes.rb @@ -59,6 +59,8 @@ defaults: { reactable: 'Idea', spam_reportable: 'Idea', post: 'Idea', followable: 'Idea', parent_param: :idea_id } do resources :images, defaults: { container_type: 'Idea' } resources :files, defaults: { container_type: 'Idea' } + resources :cosponsorships, defaults: { container_type: 'Idea' }, only: %i[index] + patch 'accept_cosponsorship', on: :member get :as_xlsx, on: :collection, action: 'index_xlsx' get :mini, on: :collection, action: 'index_mini' diff --git a/front/app/components/Form/Components/Controls/CosponsorsControl.tsx b/front/app/components/Form/Components/Controls/CosponsorsControl.tsx index 8cd4dca49faa..8d432a09c520 100644 --- a/front/app/components/Form/Components/Controls/CosponsorsControl.tsx +++ b/front/app/components/Form/Components/Controls/CosponsorsControl.tsx @@ -47,8 +47,6 @@ const CosponsorsControlInner = ({ initialCosponsorsText ); - console.log({ cosponsorsText }); - const { formatMessage } = useIntl(); const [didBlur, setDidBlur] = useState(false); From f98c3b9fb8888c1028359cea9e9a4dd42bb1c469 Mon Sep 17 00:00:00 2001 From: Iva <iva@citizenlab.co> Date: Thu, 19 Sep 2024 13:14:22 +0300 Subject: [PATCH 19/43] Fix back lint --- back/app/controllers/web_api/v1/cosponsorships_controller.rb | 4 +--- back/app/policies/cosponsorship_policy.rb | 4 ++-- back/app/serializers/web_api/v1/cosponsorship_serializer.rb | 3 +-- back/app/services/export/xlsx/value_visitor.rb | 2 +- back/app/services/input_json_schema_generator_service.rb | 2 +- back/config/routes.rb | 2 +- 6 files changed, 7 insertions(+), 10 deletions(-) diff --git a/back/app/controllers/web_api/v1/cosponsorships_controller.rb b/back/app/controllers/web_api/v1/cosponsorships_controller.rb index d00deb53119d..6bb49a7bbd0d 100644 --- a/back/app/controllers/web_api/v1/cosponsorships_controller.rb +++ b/back/app/controllers/web_api/v1/cosponsorships_controller.rb @@ -10,9 +10,7 @@ def index render json: linked_json(paginated_cosponsorships, WebApi::V1::CosponsorshipSerializer, params: jsonapi_serializer_params) end - def accept_cosponsorship - - end + def accept_cosponsorship; end private diff --git a/back/app/policies/cosponsorship_policy.rb b/back/app/policies/cosponsorship_policy.rb index baabe6e46e67..1c272538a3f8 100644 --- a/back/app/policies/cosponsorship_policy.rb +++ b/back/app/policies/cosponsorship_policy.rb @@ -8,7 +8,7 @@ def initialize(user, scope) @user = user @scope = scope end - + def resolve scope.all end @@ -17,4 +17,4 @@ def accept_cosponsorship? user.id == record.user_id end end -end \ No newline at end of file +end diff --git a/back/app/serializers/web_api/v1/cosponsorship_serializer.rb b/back/app/serializers/web_api/v1/cosponsorship_serializer.rb index 4436cc2168d5..c774c7ed968f 100644 --- a/back/app/serializers/web_api/v1/cosponsorship_serializer.rb +++ b/back/app/serializers/web_api/v1/cosponsorship_serializer.rb @@ -5,5 +5,4 @@ class WebApi::V1::CosponsorshipSerializer < WebApi::V1::BaseSerializer belongs_to :idea belongs_to :user - -end \ No newline at end of file +end diff --git a/back/app/services/export/xlsx/value_visitor.rb b/back/app/services/export/xlsx/value_visitor.rb index b51b75fbed5e..2688151a8e46 100644 --- a/back/app/services/export/xlsx/value_visitor.rb +++ b/back/app/services/export/xlsx/value_visitor.rb @@ -120,7 +120,7 @@ def visit_topic_ids(_field) end def visit_cosponsor_ids(_field) - return '' + '' end private diff --git a/back/app/services/input_json_schema_generator_service.rb b/back/app/services/input_json_schema_generator_service.rb index 7d0d3be737e9..1a9a108296c0 100644 --- a/back/app/services/input_json_schema_generator_service.rb +++ b/back/app/services/input_json_schema_generator_service.rb @@ -55,7 +55,7 @@ def visit_topic_ids(field) } end - def visit_cosponsor_ids(field) + def visit_cosponsor_ids(field) { type: 'array', uniqueItems: true, diff --git a/back/config/routes.rb b/back/config/routes.rb index 45f9fe0f96e6..cb0ce64bf7b1 100644 --- a/back/config/routes.rb +++ b/back/config/routes.rb @@ -60,7 +60,7 @@ resources :images, defaults: { container_type: 'Idea' } resources :files, defaults: { container_type: 'Idea' } resources :cosponsorships, defaults: { container_type: 'Idea' }, only: %i[index] - patch 'accept_cosponsorship', on: :member + patch 'accept_cosponsorship', on: :member get :as_xlsx, on: :collection, action: 'index_xlsx' get :mini, on: :collection, action: 'index_mini' From 76a9c5da800beb990b4c72a4ba554025609c7c2b Mon Sep 17 00:00:00 2001 From: Iva <iva@citizenlab.co> Date: Thu, 19 Sep 2024 13:23:08 +0300 Subject: [PATCH 20/43] Fix most specs --- back/app/models/user.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/back/app/models/user.rb b/back/app/models/user.rb index ff2934d2add1..a4612d775d89 100644 --- a/back/app/models/user.rb +++ b/back/app/models/user.rb @@ -145,7 +145,7 @@ def oldest_admin has_many :attended_events, through: :event_attendances, source: :event has_many :follows, -> { order(:followable_id) }, class_name: 'Follower', dependent: :destroy has_many :cosponsors_initiatives, dependent: :destroy - has_many :cosponsorships, dependent: :destroy, foreign_key: :cosponsor_id + has_many :cosponsorships, dependent: :destroy has_many :cosponsored_ideas, through: :cosponsorships, source: :idea before_validation :sanitize_bio_multiloc, if: :bio_multiloc From 93133dbeb69d4a687db3be7b7b2c186490efc8ef Mon Sep 17 00:00:00 2001 From: Iva <iva@citizenlab.co> Date: Thu, 19 Sep 2024 14:27:44 +0300 Subject: [PATCH 21/43] Fix default fields ordering --- back/lib/participation_method/ideation.rb | 53 +++++++++++++---------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/back/lib/participation_method/ideation.rb b/back/lib/participation_method/ideation.rb index 4b2b9d74a328..a0afad9bc46f 100644 --- a/back/lib/participation_method/ideation.rb +++ b/back/lib/participation_method/ideation.rb @@ -36,6 +36,10 @@ def budget_in_form?(user) end end + def cosponsors_in_form? + phase.participation_method == 'proposals' + end + # Locks mirror the name of the fields whose default values cannot be changed (ie are locked) def constraints result = { @@ -271,29 +275,6 @@ def default_fields(custom_form) ordering: 8, answer_visible_to: CustomField::VISIBLE_TO_PUBLIC ), - CustomField.new( - id: SecureRandom.uuid, - resource: custom_form, - key: 'cosponsor_ids', - code: 'cosponsor_ids', - input_type: 'cosponsor_ids', - title_multiloc: multiloc_service.i18n_to_multiloc( - 'custom_fields.ideas.consponsor_ids.title', - locales: CL2_SUPPORTED_LOCALES - ), - description_multiloc: begin - multiloc_service.i18n_to_multiloc( - 'custom_fields.ideas.consponsor_ids.description', - locales: CL2_SUPPORTED_LOCALES - ) - rescue StandardError - {} - end, - required: false, - enabled: false, - ordering: proposed_budget_in_form? ? 10 : 9, - answer_visible_to: CustomField::VISIBLE_TO_PUBLIC - ) ] if proposed_budget_in_form? fields << CustomField.new( @@ -320,6 +301,32 @@ def default_fields(custom_form) answer_visible_to: CustomField::VISIBLE_TO_PUBLIC ) end + + if cosponsors_in_form? + fields << CustomField.new( + id: SecureRandom.uuid, + resource: custom_form, + key: 'cosponsor_ids', + code: 'cosponsor_ids', + input_type: 'cosponsor_ids', + title_multiloc: multiloc_service.i18n_to_multiloc( + 'custom_fields.ideas.consponsor_ids.title', + locales: CL2_SUPPORTED_LOCALES + ), + description_multiloc: begin + multiloc_service.i18n_to_multiloc( + 'custom_fields.ideas.consponsor_ids.description', + locales: CL2_SUPPORTED_LOCALES + ) + rescue StandardError + {} + end, + required: false, + enabled: false, + ordering: proposed_budget_in_form? ? 10 : 9, + answer_visible_to: CustomField::VISIBLE_TO_PUBLIC + ) + end fields end From e32f09f065481bcdbb4862780ec1c575d1b787ea Mon Sep 17 00:00:00 2001 From: Iva <iva@citizenlab.co> Date: Thu, 19 Sep 2024 14:45:05 +0300 Subject: [PATCH 22/43] Improve participation method check --- back/lib/participation_method/ideation.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/back/lib/participation_method/ideation.rb b/back/lib/participation_method/ideation.rb index a0afad9bc46f..2782163923b6 100644 --- a/back/lib/participation_method/ideation.rb +++ b/back/lib/participation_method/ideation.rb @@ -7,7 +7,7 @@ def self.method_str end def allowed_extra_field_input_types - %w[section number linear_scale text multiline_text select multiselect multiselect_image cosponsor_ids] + %w[section number linear_scale text multiline_text select multiselect multiselect_image] end def allowed_ideas_orders @@ -37,7 +37,7 @@ def budget_in_form?(user) end def cosponsors_in_form? - phase.participation_method == 'proposals' + phase ? phase.participation_method == 'proposals' : false end # Locks mirror the name of the fields whose default values cannot be changed (ie are locked) @@ -301,7 +301,7 @@ def default_fields(custom_form) answer_visible_to: CustomField::VISIBLE_TO_PUBLIC ) end - + if cosponsors_in_form? fields << CustomField.new( id: SecureRandom.uuid, From e04da57d86532fda23f7f37c11507d07eaa8b2c4 Mon Sep 17 00:00:00 2001 From: Iva <iva@citizenlab.co> Date: Thu, 19 Sep 2024 14:59:41 +0300 Subject: [PATCH 23/43] FIx remaining specs --- back/lib/participation_method/ideation.rb | 44 +++++++++---------- .../participation_method/proposals_spec.rb | 1 + back/spec/models/custom_field_spec.rb | 4 ++ 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/back/lib/participation_method/ideation.rb b/back/lib/participation_method/ideation.rb index 2782163923b6..5f438eef9242 100644 --- a/back/lib/participation_method/ideation.rb +++ b/back/lib/participation_method/ideation.rb @@ -274,7 +274,7 @@ def default_fields(custom_form) enabled: true, ordering: 8, answer_visible_to: CustomField::VISIBLE_TO_PUBLIC - ), + ) ] if proposed_budget_in_form? fields << CustomField.new( @@ -304,28 +304,28 @@ def default_fields(custom_form) if cosponsors_in_form? fields << CustomField.new( - id: SecureRandom.uuid, - resource: custom_form, - key: 'cosponsor_ids', - code: 'cosponsor_ids', - input_type: 'cosponsor_ids', - title_multiloc: multiloc_service.i18n_to_multiloc( - 'custom_fields.ideas.consponsor_ids.title', + id: SecureRandom.uuid, + resource: custom_form, + key: 'cosponsor_ids', + code: 'cosponsor_ids', + input_type: 'cosponsor_ids', + title_multiloc: multiloc_service.i18n_to_multiloc( + 'custom_fields.ideas.consponsor_ids.title', + locales: CL2_SUPPORTED_LOCALES + ), + description_multiloc: begin + multiloc_service.i18n_to_multiloc( + 'custom_fields.ideas.consponsor_ids.description', locales: CL2_SUPPORTED_LOCALES - ), - description_multiloc: begin - multiloc_service.i18n_to_multiloc( - 'custom_fields.ideas.consponsor_ids.description', - locales: CL2_SUPPORTED_LOCALES - ) - rescue StandardError - {} - end, - required: false, - enabled: false, - ordering: proposed_budget_in_form? ? 10 : 9, - answer_visible_to: CustomField::VISIBLE_TO_PUBLIC - ) + ) + rescue StandardError + {} + end, + required: false, + enabled: false, + ordering: proposed_budget_in_form? ? 10 : 9, + answer_visible_to: CustomField::VISIBLE_TO_PUBLIC + ) end fields end diff --git a/back/spec/lib/participation_method/proposals_spec.rb b/back/spec/lib/participation_method/proposals_spec.rb index 1a5b5a24be90..098989df002d 100644 --- a/back/spec/lib/participation_method/proposals_spec.rb +++ b/back/spec/lib/participation_method/proposals_spec.rb @@ -163,6 +163,7 @@ ideation_section3 topic_ids location_description + cosponsor_ids ] end end diff --git a/back/spec/models/custom_field_spec.rb b/back/spec/models/custom_field_spec.rb index ac7e2c75a8f3..da07c30a360f 100644 --- a/back/spec/models/custom_field_spec.rb +++ b/back/spec/models/custom_field_spec.rb @@ -91,6 +91,10 @@ def visit_topic_ids(_field) 'topic_ids from visitor' end + def visit_cosponsor_ids(_field) + 'cosponsor_ids from visitor' + end + def visit_file_upload(_field) 'file_upload from visitor' end From 016a0d3afd2f801565df4f21b6b9e644e13f84c6 Mon Sep 17 00:00:00 2001 From: Iva <iva@citizenlab.co> Date: Thu, 19 Sep 2024 15:42:40 +0300 Subject: [PATCH 24/43] Add accept cosponsorship endpoint --- .../web_api/v1/cosponsorships_controller.rb | 12 ++++++++++-- back/app/policies/cosponsorship_policy.rb | 6 +++--- back/config/routes.rb | 5 +++-- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/back/app/controllers/web_api/v1/cosponsorships_controller.rb b/back/app/controllers/web_api/v1/cosponsorships_controller.rb index 6bb49a7bbd0d..9ad6765c8ae4 100644 --- a/back/app/controllers/web_api/v1/cosponsorships_controller.rb +++ b/back/app/controllers/web_api/v1/cosponsorships_controller.rb @@ -10,11 +10,19 @@ def index render json: linked_json(paginated_cosponsorships, WebApi::V1::CosponsorshipSerializer, params: jsonapi_serializer_params) end - def accept_cosponsorship; end + def accept_cosponsorship + if @cosponsorship.status == 'pending' + @cosponsorship.update(status: 'accepted') + # SideFxAcceptedCosponsorshipService.new.after_accept(@cosponsorship, current_user) + render json: WebApi::V1::CosponsorshipSerializer.new(@cosponsorship, params: jsonapi_serializer_params).serializable_hash + else + render json: { errors: @cosponsorship.errors.details }, status: :unprocessable_entity + end + end private - def set_topic + def set_cosponsorship @cosponsorship = Cosponsorship.find(params[:id]) authorize @cosponsorship end diff --git a/back/app/policies/cosponsorship_policy.rb b/back/app/policies/cosponsorship_policy.rb index 1c272538a3f8..f5f007e637f8 100644 --- a/back/app/policies/cosponsorship_policy.rb +++ b/back/app/policies/cosponsorship_policy.rb @@ -12,9 +12,9 @@ def initialize(user, scope) def resolve scope.all end + end - def accept_cosponsorship? - user.id == record.user_id - end + def accept_cosponsorship? + user.id == record.user_id end end diff --git a/back/config/routes.rb b/back/config/routes.rb index cb0ce64bf7b1..fcbd2239b193 100644 --- a/back/config/routes.rb +++ b/back/config/routes.rb @@ -59,8 +59,9 @@ defaults: { reactable: 'Idea', spam_reportable: 'Idea', post: 'Idea', followable: 'Idea', parent_param: :idea_id } do resources :images, defaults: { container_type: 'Idea' } resources :files, defaults: { container_type: 'Idea' } - resources :cosponsorships, defaults: { container_type: 'Idea' }, only: %i[index] - patch 'accept_cosponsorship', on: :member + resources :cosponsorships, defaults: { container_type: 'Idea' } do + patch 'accept_cosponsorship', on: :member + end get :as_xlsx, on: :collection, action: 'index_xlsx' get :mini, on: :collection, action: 'index_mini' From fd09c0dffd36de216b2502c79d163c1b46ae3e47 Mon Sep 17 00:00:00 2001 From: Iva <iva@citizenlab.co> Date: Thu, 19 Sep 2024 16:52:12 +0300 Subject: [PATCH 25/43] Add api --- .../__mocks__/useCosponsorships.ts | 50 +++++++++++++++ front/app/api/cosponsorship/keys.ts | 15 +++++ front/app/api/cosponsorship/types.ts | 43 +++++++++++++ .../useAcceptCosponsorshipInvitation.test.ts | 62 +++++++++++++++++++ .../useAcceptCosponsorshipInvitation.ts | 37 +++++++++++ .../cosponsorship/useCosponsorships.test.ts | 57 +++++++++++++++++ .../api/cosponsorship/useCosponsorships.ts | 34 ++++++++++ 7 files changed, 298 insertions(+) create mode 100644 front/app/api/cosponsorship/__mocks__/useCosponsorships.ts create mode 100644 front/app/api/cosponsorship/keys.ts create mode 100644 front/app/api/cosponsorship/types.ts create mode 100644 front/app/api/cosponsorship/useAcceptCosponsorshipInvitation.test.ts create mode 100644 front/app/api/cosponsorship/useAcceptCosponsorshipInvitation.ts create mode 100644 front/app/api/cosponsorship/useCosponsorships.test.ts create mode 100644 front/app/api/cosponsorship/useCosponsorships.ts diff --git a/front/app/api/cosponsorship/__mocks__/useCosponsorships.ts b/front/app/api/cosponsorship/__mocks__/useCosponsorships.ts new file mode 100644 index 000000000000..392bdae03827 --- /dev/null +++ b/front/app/api/cosponsorship/__mocks__/useCosponsorships.ts @@ -0,0 +1,50 @@ +import { ICosponsorshipData } from '../types'; + +export const cosponsorshipData: ICosponsorshipData[] = [ + { + id: '1', + type: 'cosponsorship', + attributes: { + status: 'pending', + created_at: '2021-09-10T12:00:00Z', + updated_at: '2021-09-10T12:00:00Z', + }, + relationships: { + user: { + data: { + id: '3', + }, + }, + idea: { + data: { + id: '1', + }, + }, + }, + }, + { + id: '2', + type: 'cosponsorship', + attributes: { + status: 'accepted', + created_at: '2021-09-10T12:00:00Z', + updated_at: '2021-09-10T12:00:00Z', + }, + relationships: { + user: { + data: { + id: '4', + }, + }, + idea: { + data: { + id: '2', + }, + }, + }, + }, +]; + +export default jest.fn(() => { + return { data: { data: cosponsorshipData } }; +}); diff --git a/front/app/api/cosponsorship/keys.ts b/front/app/api/cosponsorship/keys.ts new file mode 100644 index 000000000000..ed114362a156 --- /dev/null +++ b/front/app/api/cosponsorship/keys.ts @@ -0,0 +1,15 @@ +import { QueryKeys } from 'utils/cl-react-query/types'; + +import { ICosponsorshipParameters } from './types'; + +const baseKey = { type: 'cosponsorship' }; + +const cosponsorshipKeys = { + all: () => [baseKey], + lists: () => [{ ...baseKey, operation: 'list' }], + list: (params: ICosponsorshipParameters) => [ + { ...baseKey, operation: 'list', parameters: params }, + ], +} satisfies QueryKeys; + +export default cosponsorshipKeys; diff --git a/front/app/api/cosponsorship/types.ts b/front/app/api/cosponsorship/types.ts new file mode 100644 index 000000000000..de0b4e9f6cf9 --- /dev/null +++ b/front/app/api/cosponsorship/types.ts @@ -0,0 +1,43 @@ +import { ILinks } from 'typings'; + +import { Keys } from 'utils/cl-react-query/types'; + +import causesKeys from './keys'; + +export type CosponsorshipsKeys = Keys<typeof causesKeys>; + +export interface ICosponsorshipData { + id: string; + type: 'cosponsorship'; + attributes: { + status: 'pending' | 'accepted'; + created_at: string; + updated_at: string; + }; + relationships: { + user: { + data: { + id: string; + }; + }; + idea: { + data: null | { + id: string; + }; + }; + }; +} + +export interface ICosponsorships { + data: ICosponsorshipData[]; + links: ILinks; +} + +export interface ICosponsorship { + data: ICosponsorshipData; +} + +export interface ICosponsorshipParameters { + id: string; + ideaId: string; +} diff --git a/front/app/api/cosponsorship/useAcceptCosponsorshipInvitation.test.ts b/front/app/api/cosponsorship/useAcceptCosponsorshipInvitation.test.ts new file mode 100644 index 000000000000..714ad2b8a465 --- /dev/null +++ b/front/app/api/cosponsorship/useAcceptCosponsorshipInvitation.test.ts @@ -0,0 +1,62 @@ +import { renderHook, act } from '@testing-library/react-hooks'; +import { http, HttpResponse } from 'msw'; +import { setupServer } from 'msw/node'; + +import createQueryClientWrapper from 'utils/testUtils/queryClientWrapper'; + +import { cosponsorshipData } from './__mocks__/useCosponsorships'; +import useAcceptCosponsorshipInvitation from './useAcceptCosponsorshipInvitation'; + +const apiPath = '*cosponsorships/:id'; +const server = setupServer( + http.patch(apiPath, () => { + return HttpResponse.json({ data: cosponsorshipData[0] }, { status: 200 }); + }) +); + +describe('useAcceptCosponsorshipInvitation', () => { + beforeAll(() => server.listen()); + afterAll(() => server.close()); + + it('mutates data correctly', async () => { + const { result, waitFor } = renderHook( + () => useAcceptCosponsorshipInvitation(), + { + wrapper: createQueryClientWrapper(), + } + ); + + act(() => { + result.current.mutate({ + ideaId: 'ideaId', + id: 'id', + }); + }); + + await waitFor(() => expect(result.current.isSuccess).toBe(true)); + expect(result.current.data?.data).toEqual(cosponsorshipData[0]); + }); + + it('returns error correctly', async () => { + server.use( + http.patch(apiPath, () => { + return HttpResponse.json(null, { status: 500 }); + }) + ); + + const { result, waitFor } = renderHook( + () => useAcceptCosponsorshipInvitation(), + { + wrapper: createQueryClientWrapper(), + } + ); + act(() => { + result.current.mutate({ + ideaId: 'ideaId', + id: 'id', + }); + }); + await waitFor(() => expect(result.current.isError).toBe(true)); + expect(result.current.error).toBeDefined(); + }); +}); diff --git a/front/app/api/cosponsorship/useAcceptCosponsorshipInvitation.ts b/front/app/api/cosponsorship/useAcceptCosponsorshipInvitation.ts new file mode 100644 index 000000000000..555301df56eb --- /dev/null +++ b/front/app/api/cosponsorship/useAcceptCosponsorshipInvitation.ts @@ -0,0 +1,37 @@ +import { useMutation, useQueryClient } from '@tanstack/react-query'; +import { CLErrors } from 'typings'; + +import fetcher from 'utils/cl-react-query/fetcher'; + +import cosponsorshipKeys from './keys'; +import { ICosponsorship } from './types'; + +type IAcceptCosponsorshipInvitationObject = { + ideaId: string; + id: string; +}; + +const acceptCosponsorshipInvitation = ({ + ideaId, + id, +}: IAcceptCosponsorshipInvitationObject) => + fetcher<ICosponsorship>({ + path: `/ideas/${ideaId}/cosponsorships/${id}`, + action: 'patch', + }); + +const useAcceptCosponsorshipInvitation = () => { + const queryClient = useQueryClient(); + return useMutation< + ICosponsorship, + CLErrors, + IAcceptCosponsorshipInvitationObject + >({ + mutationFn: acceptCosponsorshipInvitation, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: cosponsorshipKeys.lists() }); + }, + }); +}; + +export default useAcceptCosponsorshipInvitation; diff --git a/front/app/api/cosponsorship/useCosponsorships.test.ts b/front/app/api/cosponsorship/useCosponsorships.test.ts new file mode 100644 index 000000000000..97bedfeb0e6d --- /dev/null +++ b/front/app/api/cosponsorship/useCosponsorships.test.ts @@ -0,0 +1,57 @@ +import { renderHook } from '@testing-library/react-hooks'; +import { http, HttpResponse } from 'msw'; +import { setupServer } from 'msw/node'; + +import createQueryClientWrapper from 'utils/testUtils/queryClientWrapper'; + +import { cosponsorshipData } from './__mocks__/useCosponsorships'; +import { ICosponsorshipParameters } from './types'; +import useCosponsorships from './useCosponsorships'; + +const apiPath = '*/ideas/:ideaId/cosponsorships/:id'; + +const params: ICosponsorshipParameters = { + ideaId: '1', + id: '2', +}; + +const server = setupServer( + http.get(apiPath, () => { + return HttpResponse.json({ data: cosponsorshipData }, { status: 200 }); + }) +); + +describe('useCosponsorships', () => { + beforeAll(() => server.listen()); + afterAll(() => server.close()); + + it('returns data correctly', async () => { + const { result, waitFor } = renderHook(() => useCosponsorships(params), { + wrapper: createQueryClientWrapper(), + }); + + expect(result.current.isLoading).toBe(true); + + await waitFor(() => expect(result.current.isSuccess).toBe(true)); + + expect(result.current.isLoading).toBe(false); + expect(result.current.data?.data).toEqual(cosponsorshipData); + }); + + it('returns error correctly', async () => { + server.use( + http.get(apiPath, () => { + return HttpResponse.json(null, { status: 500 }); + }) + ); + + const { result, waitFor } = renderHook(() => useCosponsorships(params), { + wrapper: createQueryClientWrapper(), + }); + + expect(result.current.isLoading).toBe(true); + await waitFor(() => expect(result.current.isError).toBe(true)); + expect(result.current.error).toBeDefined(); + expect(result.current.isLoading).toBe(false); + }); +}); diff --git a/front/app/api/cosponsorship/useCosponsorships.ts b/front/app/api/cosponsorship/useCosponsorships.ts new file mode 100644 index 000000000000..421225cc42fe --- /dev/null +++ b/front/app/api/cosponsorship/useCosponsorships.ts @@ -0,0 +1,34 @@ +import { useQuery } from '@tanstack/react-query'; +import { CLErrors } from 'typings'; + +import fetcher from 'utils/cl-react-query/fetcher'; + +import cosponsorshipsKeys from './keys'; +import { + ICosponsorships, + CosponsorshipsKeys, + ICosponsorshipParameters, +} from './types'; + +const fetchCosponsorships = ({ ideaId, id }: ICosponsorshipParameters) => + fetcher<ICosponsorships>({ + path: `/ideas/${ideaId}/cosponsorships/${id}`, + action: 'get', + }); + +const useCosponsorships = ({ ideaId, id }: ICosponsorshipParameters) => { + return useQuery< + ICosponsorships, + CLErrors, + ICosponsorships, + CosponsorshipsKeys + >({ + queryKey: cosponsorshipsKeys.list({ + ideaId, + id, + }), + queryFn: () => fetchCosponsorships({ ideaId, id }), + }); +}; + +export default useCosponsorships; From 8d5e882aca00a4f9766f53ac9c5a4fcaedb738d2 Mon Sep 17 00:00:00 2001 From: Iva <iva@citizenlab.co> Date: Thu, 19 Sep 2024 16:56:27 +0300 Subject: [PATCH 26/43] Delete unused model --- back/app/models/cosponsors_idea.rb | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 back/app/models/cosponsors_idea.rb diff --git a/back/app/models/cosponsors_idea.rb b/back/app/models/cosponsors_idea.rb deleted file mode 100644 index 24088d6967a1..000000000000 --- a/back/app/models/cosponsors_idea.rb +++ /dev/null @@ -1,26 +0,0 @@ -# frozen_string_literal: true - -# == Schema Information -# -# Table name: cosponsors_ideas -# -# cosponsor_id :uuid -# idea_id :uuid -# -# Indexes -# -# index_cosponsors_ideas_on_cosponsor_id (cosponsor_id) -# index_cosponsors_ideas_on_idea_id (idea_id) -# -# Foreign Keys -# -# fk_rails_... (cosponsor_id => users.id) -# fk_rails_... (idea_id => ideas.id) -# -class CosponsorsIdea < ApplicationRecord - belongs_to :idea - belongs_to :cosponsor, class_name: 'User' - - validates :idea, :cosponsor, presence: true - validates :cosponsor_id, uniqueness: { scope: :idea_id } -end From abba47f82648c9ff9eaf8a59165792cfc404ecf8 Mon Sep 17 00:00:00 2001 From: Iva <iva@citizenlab.co> Date: Thu, 19 Sep 2024 17:22:11 +0300 Subject: [PATCH 27/43] Add component --- front/app/api/cosponsorship/types.ts | 1 - .../cosponsorship/useCosponsorships.test.ts | 3 +-- .../api/cosponsorship/useCosponsorships.ts | 9 ++++--- .../components/Cosponsorship/index.tsx | 24 +++++++++++++++++++ front/app/containers/IdeasShow/index.tsx | 2 ++ 5 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 front/app/containers/IdeasShow/components/Cosponsorship/index.tsx diff --git a/front/app/api/cosponsorship/types.ts b/front/app/api/cosponsorship/types.ts index de0b4e9f6cf9..d07c7ee5faae 100644 --- a/front/app/api/cosponsorship/types.ts +++ b/front/app/api/cosponsorship/types.ts @@ -38,6 +38,5 @@ export interface ICosponsorship { } export interface ICosponsorshipParameters { - id: string; ideaId: string; } diff --git a/front/app/api/cosponsorship/useCosponsorships.test.ts b/front/app/api/cosponsorship/useCosponsorships.test.ts index 97bedfeb0e6d..a67ffed98709 100644 --- a/front/app/api/cosponsorship/useCosponsorships.test.ts +++ b/front/app/api/cosponsorship/useCosponsorships.test.ts @@ -8,11 +8,10 @@ import { cosponsorshipData } from './__mocks__/useCosponsorships'; import { ICosponsorshipParameters } from './types'; import useCosponsorships from './useCosponsorships'; -const apiPath = '*/ideas/:ideaId/cosponsorships/:id'; +const apiPath = '*/ideas/:ideaId/cosponsorships'; const params: ICosponsorshipParameters = { ideaId: '1', - id: '2', }; const server = setupServer( diff --git a/front/app/api/cosponsorship/useCosponsorships.ts b/front/app/api/cosponsorship/useCosponsorships.ts index 421225cc42fe..3d7eda198fba 100644 --- a/front/app/api/cosponsorship/useCosponsorships.ts +++ b/front/app/api/cosponsorship/useCosponsorships.ts @@ -10,13 +10,13 @@ import { ICosponsorshipParameters, } from './types'; -const fetchCosponsorships = ({ ideaId, id }: ICosponsorshipParameters) => +const fetchCosponsorships = ({ ideaId }: ICosponsorshipParameters) => fetcher<ICosponsorships>({ - path: `/ideas/${ideaId}/cosponsorships/${id}`, + path: `/ideas/${ideaId}/cosponsorships`, action: 'get', }); -const useCosponsorships = ({ ideaId, id }: ICosponsorshipParameters) => { +const useCosponsorships = ({ ideaId }: ICosponsorshipParameters) => { return useQuery< ICosponsorships, CLErrors, @@ -25,9 +25,8 @@ const useCosponsorships = ({ ideaId, id }: ICosponsorshipParameters) => { >({ queryKey: cosponsorshipsKeys.list({ ideaId, - id, }), - queryFn: () => fetchCosponsorships({ ideaId, id }), + queryFn: () => fetchCosponsorships({ ideaId }), }); }; diff --git a/front/app/containers/IdeasShow/components/Cosponsorship/index.tsx b/front/app/containers/IdeasShow/components/Cosponsorship/index.tsx new file mode 100644 index 000000000000..88efcab98d8b --- /dev/null +++ b/front/app/containers/IdeasShow/components/Cosponsorship/index.tsx @@ -0,0 +1,24 @@ +import React from 'react'; + +import useCosponsorships from 'api/cosponsorship/useCosponsorships'; + +import useFeatureFlag from 'hooks/useFeatureFlag'; + +const Cosponsorship = ({ ideaId }: { ideaId: string }) => { + const isCosponsorshipEnabled = useFeatureFlag({ + name: 'input_cosponsorship', + }); + + const { data: cosponsors } = useCosponsorships({ + ideaId, + }); + + if (!isCosponsorshipEnabled) { + return null; + } + + console.log(cosponsors); + return <div>Cosponsorship</div>; +}; + +export default Cosponsorship; diff --git a/front/app/containers/IdeasShow/index.tsx b/front/app/containers/IdeasShow/index.tsx index cb3207602dfa..24ca31274801 100644 --- a/front/app/containers/IdeasShow/index.tsx +++ b/front/app/containers/IdeasShow/index.tsx @@ -26,6 +26,7 @@ import { FormattedMessage } from 'utils/cl-intl'; import { usePermission } from 'utils/permissions'; import Container from './components/Container'; +import Cosponsorship from './components/Cosponsorship'; import IdeaTitle from './components/IdeaTitle'; import MetaInformation from './components/MetaInformation'; import ProposalInfo from './components/ProposalInfo'; @@ -124,6 +125,7 @@ export const IdeasShow = ({ projectId={project.data.id} translateButtonClicked={translateButtonIsClicked} /> + <Cosponsorship ideaId={ideaId} /> <ProjectLink project={project.data} /> {ideaImageLarge && ( <Image src={ideaImageLarge} alt="" id="e2e-idea-image" /> From 7e589f53e3dd533a8c3a6718c85920ceccc42763 Mon Sep 17 00:00:00 2001 From: Iva <iva@citizenlab.co> Date: Tue, 24 Sep 2024 13:28:54 +0300 Subject: [PATCH 28/43] Add cosponsorship flow to idea page --- .../web_api/v1/cosponsorships_controller.rb | 6 ++ .../useAcceptCosponsorshipInvitation.ts | 2 +- .../Cosponsorship/CosponsorsList.tsx | 80 +++++++++++++++++++ .../Cosponsorship/RequestToCosponsor.tsx | 77 ++++++++++++++++++ .../components/Cosponsorship/index.tsx | 17 ++-- .../components/Cosponsorship/messages.ts | 28 +++++++ .../components/RightColumnDesktop/index.tsx | 6 +- front/app/containers/IdeasShow/index.tsx | 3 +- 8 files changed, 208 insertions(+), 11 deletions(-) create mode 100644 front/app/containers/IdeasShow/components/Cosponsorship/CosponsorsList.tsx create mode 100644 front/app/containers/IdeasShow/components/Cosponsorship/RequestToCosponsor.tsx create mode 100644 front/app/containers/IdeasShow/components/Cosponsorship/messages.ts diff --git a/back/app/controllers/web_api/v1/cosponsorships_controller.rb b/back/app/controllers/web_api/v1/cosponsorships_controller.rb index 9ad6765c8ae4..ccbd10e4bbb6 100644 --- a/back/app/controllers/web_api/v1/cosponsorships_controller.rb +++ b/back/app/controllers/web_api/v1/cosponsorships_controller.rb @@ -6,6 +6,12 @@ class WebApi::V1::CosponsorshipsController < ApplicationController def index cosponsorships = policy_scope(Cosponsorship) + + # Filter by idea id param + if params[:idea_id] + cosponsorships = cosponsorships.where(idea_id: params[:idea_id]) + end + paginated_cosponsorships = paginate cosponsorships render json: linked_json(paginated_cosponsorships, WebApi::V1::CosponsorshipSerializer, params: jsonapi_serializer_params) end diff --git a/front/app/api/cosponsorship/useAcceptCosponsorshipInvitation.ts b/front/app/api/cosponsorship/useAcceptCosponsorshipInvitation.ts index 555301df56eb..39d1b0581bc9 100644 --- a/front/app/api/cosponsorship/useAcceptCosponsorshipInvitation.ts +++ b/front/app/api/cosponsorship/useAcceptCosponsorshipInvitation.ts @@ -16,7 +16,7 @@ const acceptCosponsorshipInvitation = ({ id, }: IAcceptCosponsorshipInvitationObject) => fetcher<ICosponsorship>({ - path: `/ideas/${ideaId}/cosponsorships/${id}`, + path: `/ideas/${ideaId}/cosponsorships/${id}/accept_cosponsorship`, action: 'patch', }); diff --git a/front/app/containers/IdeasShow/components/Cosponsorship/CosponsorsList.tsx b/front/app/containers/IdeasShow/components/Cosponsorship/CosponsorsList.tsx new file mode 100644 index 000000000000..ddfcac4e1ec2 --- /dev/null +++ b/front/app/containers/IdeasShow/components/Cosponsorship/CosponsorsList.tsx @@ -0,0 +1,80 @@ +import React from 'react'; + +import { Title, Box, Text } from '@citizenlab/cl2-component-library'; + +import useCosponsorships from 'api/cosponsorship/useCosponsorships'; +import useIdeaById from 'api/ideas/useIdeaById'; +import useAuthUser from 'api/me/useAuthUser'; + +import useFeatureFlag from 'hooks/useFeatureFlag'; + +import Avatar from 'components/Avatar'; +import UserName from 'components/UI/UserName'; + +import { useIntl } from 'utils/cl-intl'; +import { isAdmin } from 'utils/permissions/roles'; + +import messages from './messages'; +import { BorderContainer } from './RequestToCosponsor'; + +const CosponsorsList = ({ ideaId }: { ideaId: string }) => { + const isCosponsorshipEnabled = useFeatureFlag({ + name: 'input_cosponsorship', + }); + const { data: authUser } = useAuthUser(); + const { data: idea } = useIdeaById(ideaId); + const { formatMessage } = useIntl(); + + const { data: cosponsors } = useCosponsorships({ + ideaId, + }); + + if (!isCosponsorshipEnabled) { + return null; + } + + const viewPendingCosponsors = + authUser?.data?.id === idea?.data?.relationships?.author?.data?.id || + isAdmin(authUser); + + const relevantCosponsors = + cosponsors?.data.filter( + (cosponsor) => + cosponsor.attributes.status === 'accepted' || + (viewPendingCosponsors && cosponsor.attributes.status === 'pending') + ) || []; + + if (relevantCosponsors.length === 0) { + return null; + } + + return ( + <BorderContainer> + <Title variant="h3" mt="0px"> + {formatMessage(messages.cosponsors)} + + {relevantCosponsors.map((cosponsor) => ( + + + + + {cosponsor.attributes.status === 'pending' && ( + {`(${formatMessage(messages.pending)})`} + )} + + + ))} + + ); +}; + +export default CosponsorsList; diff --git a/front/app/containers/IdeasShow/components/Cosponsorship/RequestToCosponsor.tsx b/front/app/containers/IdeasShow/components/Cosponsorship/RequestToCosponsor.tsx new file mode 100644 index 000000000000..e0a90aabcbe6 --- /dev/null +++ b/front/app/containers/IdeasShow/components/Cosponsorship/RequestToCosponsor.tsx @@ -0,0 +1,77 @@ +import React from 'react'; + +import { + Button, + colors, + defaultCardStyle, + Title, + Text, +} from '@citizenlab/cl2-component-library'; +import styled from 'styled-components'; + +import useAcceptCosponsorshipInvitation from 'api/cosponsorship/useAcceptCosponsorshipInvitation'; +import useCosponsorships from 'api/cosponsorship/useCosponsorships'; +import useAuthUser from 'api/me/useAuthUser'; + +import { useIntl } from 'utils/cl-intl'; + +import messages from './messages'; + +export const BorderContainer = styled.div` + padding: 28px; + border: 1px solid ${colors.borderLight}; + ${defaultCardStyle}; +`; + +interface Props { + ideaId: string; +} + +const RequestToCosponsor = ({ ideaId }: Props) => { + const { mutate: acceptInitiativeConsponsorshipInvite, isLoading } = + useAcceptCosponsorshipInvitation(); + + const { data: cosponsors } = useCosponsorships({ + ideaId, + }); + + const { data: authUser } = useAuthUser(); + const { formatMessage } = useIntl(); + + const invitedCosponsor = cosponsors?.data.find( + (cosponsor) => cosponsor.relationships.user.data.id === authUser?.data.id + ); + const isInvitationPending = invitedCosponsor?.attributes.status === 'pending'; + + if (invitedCosponsor) { + return ( + + + {formatMessage(messages.cosponsorInvitation)} + + {formatMessage(messages.cosponsorInvitationDescription)} + + + + ); + } + + return null; +}; + +export default RequestToCosponsor; diff --git a/front/app/containers/IdeasShow/components/Cosponsorship/index.tsx b/front/app/containers/IdeasShow/components/Cosponsorship/index.tsx index 88efcab98d8b..affa8de36bbf 100644 --- a/front/app/containers/IdeasShow/components/Cosponsorship/index.tsx +++ b/front/app/containers/IdeasShow/components/Cosponsorship/index.tsx @@ -1,24 +1,27 @@ import React from 'react'; -import useCosponsorships from 'api/cosponsorship/useCosponsorships'; +import { Box } from '@citizenlab/cl2-component-library'; import useFeatureFlag from 'hooks/useFeatureFlag'; +import CosponsorsList from './CosponsorsList'; +import RequestToCosponsor from './RequestToCosponsor'; + const Cosponsorship = ({ ideaId }: { ideaId: string }) => { const isCosponsorshipEnabled = useFeatureFlag({ name: 'input_cosponsorship', }); - const { data: cosponsors } = useCosponsorships({ - ideaId, - }); - if (!isCosponsorshipEnabled) { return null; } - console.log(cosponsors); - return
Cosponsorship
; + return ( + + + + + ); }; export default Cosponsorship; diff --git a/front/app/containers/IdeasShow/components/Cosponsorship/messages.ts b/front/app/containers/IdeasShow/components/Cosponsorship/messages.ts new file mode 100644 index 000000000000..6c5f7bd53067 --- /dev/null +++ b/front/app/containers/IdeasShow/components/Cosponsorship/messages.ts @@ -0,0 +1,28 @@ +import { defineMessages } from 'react-intl'; + +export default defineMessages({ + cosponsors: { + id: 'app.containers.IdeasShow.Cosponsorship.cosponsors', + defaultMessage: 'Cosponsors', + }, + pending: { + id: 'app.containers.IdeasShow.Cosponsorship.pending', + defaultMessage: 'pending', + }, + cosponsorInvitation: { + id: 'app.containers.IdeasShow.Cosponsorship.cosponsorInvitation', + defaultMessage: 'Cosponsorship invitation', + }, + cosponsorInvitationDescription: { + id: 'app.containers.IdeasShow.Cosponsorship.cosponsorDescription', + defaultMessage: 'You have been invited become a cosponsor.', + }, + cosponsorInvitationAccepted: { + id: 'app.containers.IdeasShow.Cosponsorship.cosponsorInvitationAccepted', + defaultMessage: 'Invitation accepted', + }, + cosponsorAcceptInvitation: { + id: 'app.containers.IdeasShow.Cosponsorship.cosponsorAcceptInvitation', + defaultMessage: 'Accept invitation', + }, +}); diff --git a/front/app/containers/IdeasShow/components/RightColumnDesktop/index.tsx b/front/app/containers/IdeasShow/components/RightColumnDesktop/index.tsx index 00e693ee2162..e59685eeccdd 100644 --- a/front/app/containers/IdeasShow/components/RightColumnDesktop/index.tsx +++ b/front/app/containers/IdeasShow/components/RightColumnDesktop/index.tsx @@ -21,6 +21,7 @@ import { rightColumnWidthDesktop } from '../../styleConstants'; import GoToCommentsButton from '../Buttons/GoToCommentsButton'; import IdeaSharingButton from '../Buttons/IdeaSharingButton'; import SharingButtonComponent from '../Buttons/SharingButtonComponent'; +import Cosponsorship from '../Cosponsorship'; import MetaInformation from '../MetaInformation'; import ProposalInfo from '../ProposalInfo'; @@ -56,7 +57,6 @@ const RightColumnDesktop = ({ const commentingEnabled = !!idea?.data.attributes.action_descriptors.commenting_idea.enabled; - // showReactionControl const participationMethod = phase?.attributes.participation_method; const reactingActionDescriptor = @@ -91,7 +91,7 @@ const RightColumnDesktop = ({ className={className} > - {showInteractionsContainer && ( + {showInteractionsContainer && participationMethod && ( )} + + - {ideaImageLarge && ( @@ -144,6 +143,8 @@ export const IdeasShow = ({ translateButtonClicked={translateButtonIsClicked} /> + {compact && } + {compact && statusId && ( {participationContext?.attributes.participation_method === From 20f7e4297e52bb14df463bfd2a01d80f166d1004 Mon Sep 17 00:00:00 2001 From: CircleCI Date: Tue, 24 Sep 2024 10:31:48 +0000 Subject: [PATCH 29/43] Translations updated by CI (extract-intl) --- front/app/translations/en.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/front/app/translations/en.json b/front/app/translations/en.json index 5f88c5c8c111..734318d1e0ef 100644 --- a/front/app/translations/en.json +++ b/front/app/translations/en.json @@ -1308,6 +1308,12 @@ "app.containers.IdeasNewPage.projectMetaTitle1": "Add new project to project | {orgName}", "app.containers.IdeasNewPage.questionMetaTitle1": "Add new question to project | {orgName}", "app.containers.IdeasNewPage.surveyNewMetaTitle1": "Add survey response to project | {orgName}", + "app.containers.IdeasShow.Cosponsorship.cosponsorAcceptInvitation": "Accept invitation", + "app.containers.IdeasShow.Cosponsorship.cosponsorDescription": "You have been invited become a cosponsor.", + "app.containers.IdeasShow.Cosponsorship.cosponsorInvitation": "Cosponsorship invitation", + "app.containers.IdeasShow.Cosponsorship.cosponsorInvitationAccepted": "Invitation accepted", + "app.containers.IdeasShow.Cosponsorship.cosponsors": "Cosponsors", + "app.containers.IdeasShow.Cosponsorship.pending": "pending", "app.containers.IdeasShow.MetaInformation.attachments": "Attachments", "app.containers.IdeasShow.MetaInformation.byUserOnDate": "{userName} on {date}", "app.containers.IdeasShow.MetaInformation.currentStatus": "Current status", From da554ef34e3d4950b85b53a461c7e57d483b4931 Mon Sep 17 00:00:00 2001 From: Iva Date: Tue, 24 Sep 2024 15:15:04 +0300 Subject: [PATCH 30/43] Add specs --- back/spec/acceptance/cosponsorships_spec.rb | 59 +++++++++++++++++++++ back/spec/factories/cosponsorships.rb | 9 ++++ 2 files changed, 68 insertions(+) create mode 100644 back/spec/acceptance/cosponsorships_spec.rb create mode 100644 back/spec/factories/cosponsorships.rb diff --git a/back/spec/acceptance/cosponsorships_spec.rb b/back/spec/acceptance/cosponsorships_spec.rb new file mode 100644 index 000000000000..441cc4d6b6b2 --- /dev/null +++ b/back/spec/acceptance/cosponsorships_spec.rb @@ -0,0 +1,59 @@ + + +require 'rails_helper' +require 'rspec_api_documentation/dsl' + + +resource 'Cosponsorships' do + + explanation 'Cosponsorships are the relationships between users and ideas. They can be pending or accepted.' + header 'Content-Type', 'application/json' + + before do + header 'Content-Type', 'application/json' + @project = create(:single_phase_proposals_project) + @idea = create(:idea, project: @project, phases: @project.phases) + @user = create(:user) + @cosponsorship = create(:cosponsorship, user: @user, idea: @idea) + end + + get 'web_api/v1/ideas/:idea_id/cosponsorships' do + with_options scope: :page do + parameter :number, 'Page number' + parameter :size, 'Number of cosponsorships per page' + end + + before do + @cosponsorships = create_list(:cosponsorship, 2, idea: @idea) + end + + example 'List all cosponsorships for an idea' do + do_request idea_id: @idea.id + expect(status).to eq 200 + expect(response_data.size).to eq 3 + end + end + + context 'when the user is the invited user' do + patch 'web_api/v1/ideas/:idea_id/cosponsorships/:cosponsorship_id/accept_cosponsorship' do + before do + header 'Authorization', authorization_header(@user) + end + + example_request 'Accept a cosponsorship when the user is the invited user' do + expect(status).to eq 200 + expect(response_data.dig(:data, :attributes, :status)).to eq 'accepted' + end + end + end + + context 'when the user is not the invited user' do + patch 'web_api/v1/ideas/:idea_id/cosponsorships/:cosponsorship_id/accept_cosponsorship' do + + example_request 'Accept a cosponsorship when the user is not the invited user' do + expect(status).to eq 401 + end + + end + end +end diff --git a/back/spec/factories/cosponsorships.rb b/back/spec/factories/cosponsorships.rb new file mode 100644 index 000000000000..da468e443cca --- /dev/null +++ b/back/spec/factories/cosponsorships.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :cosponsorship do + status { 'pending' } + association :idea, factory: :idea + association :user, factory: :user + end +end From 14cecc26c7304c55446cdf60f223e58ba077070b Mon Sep 17 00:00:00 2001 From: Iva Date: Tue, 24 Sep 2024 15:35:47 +0300 Subject: [PATCH 31/43] Fix back lint --- .../web_api/v1/cosponsorships_controller.rb | 2 +- back/spec/acceptance/cosponsorships_spec.rb | 16 +++++----------- back/spec/factories/cosponsorships.rb | 4 ++-- .../useAcceptCosponsorshipInvitation.test.ts | 2 +- 4 files changed, 9 insertions(+), 15 deletions(-) diff --git a/back/app/controllers/web_api/v1/cosponsorships_controller.rb b/back/app/controllers/web_api/v1/cosponsorships_controller.rb index ccbd10e4bbb6..41a09308062d 100644 --- a/back/app/controllers/web_api/v1/cosponsorships_controller.rb +++ b/back/app/controllers/web_api/v1/cosponsorships_controller.rb @@ -11,7 +11,7 @@ def index if params[:idea_id] cosponsorships = cosponsorships.where(idea_id: params[:idea_id]) end - + paginated_cosponsorships = paginate cosponsorships render json: linked_json(paginated_cosponsorships, WebApi::V1::CosponsorshipSerializer, params: jsonapi_serializer_params) end diff --git a/back/spec/acceptance/cosponsorships_spec.rb b/back/spec/acceptance/cosponsorships_spec.rb index 441cc4d6b6b2..77d86d87bf26 100644 --- a/back/spec/acceptance/cosponsorships_spec.rb +++ b/back/spec/acceptance/cosponsorships_spec.rb @@ -1,11 +1,7 @@ - - require 'rails_helper' require 'rspec_api_documentation/dsl' - resource 'Cosponsorships' do - explanation 'Cosponsorships are the relationships between users and ideas. They can be pending or accepted.' header 'Content-Type', 'application/json' @@ -39,7 +35,7 @@ before do header 'Authorization', authorization_header(@user) end - + example_request 'Accept a cosponsorship when the user is the invited user' do expect(status).to eq 200 expect(response_data.dig(:data, :attributes, :status)).to eq 'accepted' @@ -48,12 +44,10 @@ end context 'when the user is not the invited user' do - patch 'web_api/v1/ideas/:idea_id/cosponsorships/:cosponsorship_id/accept_cosponsorship' do - - example_request 'Accept a cosponsorship when the user is not the invited user' do - expect(status).to eq 401 - end - + patch 'web_api/v1/ideas/:idea_id/cosponsorships/:cosponsorship_id/accept_cosponsorship' do + example_request 'Accept a cosponsorship when the user is not the invited user' do + expect(status).to eq 401 end + end end end diff --git a/back/spec/factories/cosponsorships.rb b/back/spec/factories/cosponsorships.rb index da468e443cca..9fd424fdc1dc 100644 --- a/back/spec/factories/cosponsorships.rb +++ b/back/spec/factories/cosponsorships.rb @@ -3,7 +3,7 @@ FactoryBot.define do factory :cosponsorship do status { 'pending' } - association :idea, factory: :idea - association :user, factory: :user + association :idea + association :user end end diff --git a/front/app/api/cosponsorship/useAcceptCosponsorshipInvitation.test.ts b/front/app/api/cosponsorship/useAcceptCosponsorshipInvitation.test.ts index 714ad2b8a465..384e34ab4c54 100644 --- a/front/app/api/cosponsorship/useAcceptCosponsorshipInvitation.test.ts +++ b/front/app/api/cosponsorship/useAcceptCosponsorshipInvitation.test.ts @@ -7,7 +7,7 @@ import createQueryClientWrapper from 'utils/testUtils/queryClientWrapper'; import { cosponsorshipData } from './__mocks__/useCosponsorships'; import useAcceptCosponsorshipInvitation from './useAcceptCosponsorshipInvitation'; -const apiPath = '*cosponsorships/:id'; +const apiPath = '*cosponsorships/:id/accept_cosponsorship'; const server = setupServer( http.patch(apiPath, () => { return HttpResponse.json({ data: cosponsorshipData[0] }, { status: 200 }); From 68e126780e8e586e096f2c878848070ebbd87371 Mon Sep 17 00:00:00 2001 From: Iva Date: Tue, 24 Sep 2024 18:08:10 +0300 Subject: [PATCH 32/43] Fix spec and prposals CTA --- back/spec/acceptance/cosponsorships_spec.rb | 5 ++++- front/app/utils/actionTakingRules.ts | 5 +++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/back/spec/acceptance/cosponsorships_spec.rb b/back/spec/acceptance/cosponsorships_spec.rb index 77d86d87bf26..1b13b1f2303b 100644 --- a/back/spec/acceptance/cosponsorships_spec.rb +++ b/back/spec/acceptance/cosponsorships_spec.rb @@ -13,6 +13,9 @@ @cosponsorship = create(:cosponsorship, user: @user, idea: @idea) end + let (:idea_id) { @idea.id } + let (:cosponsorship_id) { @cosponsorship.id } + get 'web_api/v1/ideas/:idea_id/cosponsorships' do with_options scope: :page do parameter :number, 'Page number' @@ -38,7 +41,7 @@ example_request 'Accept a cosponsorship when the user is the invited user' do expect(status).to eq 200 - expect(response_data.dig(:data, :attributes, :status)).to eq 'accepted' + expect(response_data.dig(:attributes, :status)).to eq 'accepted' end end end diff --git a/front/app/utils/actionTakingRules.ts b/front/app/utils/actionTakingRules.ts index e1587cbed08f..b4d125cb7291 100644 --- a/front/app/utils/actionTakingRules.ts +++ b/front/app/utils/actionTakingRules.ts @@ -149,11 +149,12 @@ export const getIdeaPostingRules = ({ // timeline if (phase) { - // not an enabled ideation or native survey phase + // not an enabled ideation or native survey or proposals phase if ( !( (phase.attributes.participation_method === 'ideation' || - phase.attributes.participation_method === 'native_survey') && + phase.attributes.participation_method === 'native_survey' || + phase.attributes.participation_method === 'proposals') && phase.attributes.submission_enabled && disabled_reason !== 'posting_not_supported' ) From b3bab3e9293b8b9929fba80db51a0818e7b144b2 Mon Sep 17 00:00:00 2001 From: Iva Date: Wed, 25 Sep 2024 11:34:56 +0300 Subject: [PATCH 33/43] Fix back lint --- back/spec/acceptance/cosponsorships_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/back/spec/acceptance/cosponsorships_spec.rb b/back/spec/acceptance/cosponsorships_spec.rb index 1b13b1f2303b..3189dcc16a78 100644 --- a/back/spec/acceptance/cosponsorships_spec.rb +++ b/back/spec/acceptance/cosponsorships_spec.rb @@ -13,8 +13,8 @@ @cosponsorship = create(:cosponsorship, user: @user, idea: @idea) end - let (:idea_id) { @idea.id } - let (:cosponsorship_id) { @cosponsorship.id } + let(:idea_id) { @idea.id } + let(:cosponsorship_id) { @cosponsorship.id } get 'web_api/v1/ideas/:idea_id/cosponsorships' do with_options scope: :page do From 1c61d2d1f7f3ec71c647bdac396ccd090c812397 Mon Sep 17 00:00:00 2001 From: Iva Date: Thu, 26 Sep 2024 11:44:41 +0300 Subject: [PATCH 34/43] Make copy consistent --- front/app/components/InitiativeForm/messages.ts | 8 ++++---- front/app/components/admin/PostManager/messages.ts | 4 ++-- front/app/containers/Admin/initiatives/messages.ts | 4 ++-- .../IdeasShow/components/Cosponsorship/messages.ts | 14 +++++++------- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/front/app/components/InitiativeForm/messages.ts b/front/app/components/InitiativeForm/messages.ts index 992105dcf871..38efd5eccf90 100644 --- a/front/app/components/InitiativeForm/messages.ts +++ b/front/app/components/InitiativeForm/messages.ts @@ -107,8 +107,8 @@ export default defineMessages({ defaultMessage: 'Type an address', }, cosponsorSectionTitle: { - id: 'app.components.InitiativeForm.cosponsorSectionTitle', - defaultMessage: 'Cosponsors needed for review', + id: 'app.components.InitiativeForm.co-sponsorSectionTitle', + defaultMessage: 'Co-sponsors needed for review', }, cosponsorSubtextBeforeInput: { id: 'app.components.InitiativeForm.cosponsorSubtextBeforeInput', @@ -197,7 +197,7 @@ export default defineMessages({ defaultMessage: 'Start typing a name to search', }, cosponsorsLabel: { - id: 'app.components.InitiativeForm.cosponsorsLabel', - defaultMessage: 'Cosponsors', + id: 'app.components.InitiativeForm.co-sponsorsLabel', + defaultMessage: 'Co-sponsors', }, }); diff --git a/front/app/components/admin/PostManager/messages.ts b/front/app/components/admin/PostManager/messages.ts index fd3415642b17..efaf60e113ee 100644 --- a/front/app/components/admin/PostManager/messages.ts +++ b/front/app/components/admin/PostManager/messages.ts @@ -309,8 +309,8 @@ export default defineMessages({ defaultMessage: 'Imported', }, cosponsors: { - id: 'app.components.admin.PostManager.cosponsors', - defaultMessage: 'Cosponsors', + id: 'app.components.admin.PostManager.co-sponsors', + defaultMessage: 'Co-sponsors', }, prescreeningTooltipUpsell: { id: 'app.components.admin.PostManager.screeningTooltip', diff --git a/front/app/containers/Admin/initiatives/messages.ts b/front/app/containers/Admin/initiatives/messages.ts index 8c9a9665392c..b59809973b10 100644 --- a/front/app/containers/Admin/initiatives/messages.ts +++ b/front/app/containers/Admin/initiatives/messages.ts @@ -169,8 +169,8 @@ export default defineMessages({ defaultMessage: 'Review', }, cosponsors: { - id: 'app.containers.Admin.initiatives.cosponsors', - defaultMessage: 'Cosponsors', + id: 'app.containers.Admin.initiatives.co-sponsors', + defaultMessage: 'Co-sponsors', }, thresholds: { id: 'app.containers.Admin.initiatives.thresholds', diff --git a/front/app/containers/IdeasShow/components/Cosponsorship/messages.ts b/front/app/containers/IdeasShow/components/Cosponsorship/messages.ts index 6c5f7bd53067..ed2c17a93bd4 100644 --- a/front/app/containers/IdeasShow/components/Cosponsorship/messages.ts +++ b/front/app/containers/IdeasShow/components/Cosponsorship/messages.ts @@ -2,27 +2,27 @@ import { defineMessages } from 'react-intl'; export default defineMessages({ cosponsors: { - id: 'app.containers.IdeasShow.Cosponsorship.cosponsors', - defaultMessage: 'Cosponsors', + id: 'app.containers.IdeasShow.Cosponsorship.co-sponsors', + defaultMessage: 'Co-sponsors', }, pending: { id: 'app.containers.IdeasShow.Cosponsorship.pending', defaultMessage: 'pending', }, cosponsorInvitation: { - id: 'app.containers.IdeasShow.Cosponsorship.cosponsorInvitation', - defaultMessage: 'Cosponsorship invitation', + id: 'app.containers.IdeasShow.Cosponsorship.co-sponsorInvitation', + defaultMessage: 'Co-sponsorship invitation', }, cosponsorInvitationDescription: { - id: 'app.containers.IdeasShow.Cosponsorship.cosponsorDescription', - defaultMessage: 'You have been invited become a cosponsor.', + id: 'app.containers.IdeasShow.Cosponsorship.co-sponsorDescription', + defaultMessage: 'You have been invited become a co-sponsor.', }, cosponsorInvitationAccepted: { id: 'app.containers.IdeasShow.Cosponsorship.cosponsorInvitationAccepted', defaultMessage: 'Invitation accepted', }, cosponsorAcceptInvitation: { - id: 'app.containers.IdeasShow.Cosponsorship.cosponsorAcceptInvitation', + id: 'app.containers.IdeasShow.Cosponsorship.co-sponsorAcceptInvitation', defaultMessage: 'Accept invitation', }, }); From bde66718f2e51ab5db80585b333768c16631ec41 Mon Sep 17 00:00:00 2001 From: CircleCI Date: Thu, 26 Sep 2024 08:47:32 +0000 Subject: [PATCH 35/43] Translations updated by CI (extract-intl) --- front/app/translations/admin/ar-SA.json | 2 -- front/app/translations/admin/ca-ES.json | 2 -- front/app/translations/admin/cy-GB.json | 2 -- front/app/translations/admin/da-DK.json | 2 -- front/app/translations/admin/de-DE.json | 2 -- front/app/translations/admin/el-GR.json | 2 -- front/app/translations/admin/en-CA.json | 2 -- front/app/translations/admin/en-GB.json | 2 -- front/app/translations/admin/en-IE.json | 2 -- front/app/translations/admin/en.json | 4 ++-- front/app/translations/admin/es-CL.json | 2 -- front/app/translations/admin/es-ES.json | 2 -- front/app/translations/admin/fi-FI.json | 2 -- front/app/translations/admin/fr-BE.json | 2 -- front/app/translations/admin/fr-FR.json | 2 -- front/app/translations/admin/hr-HR.json | 2 -- front/app/translations/admin/it-IT.json | 2 -- front/app/translations/admin/lv-LV.json | 2 -- front/app/translations/admin/nb-NO.json | 2 -- front/app/translations/admin/nl-BE.json | 2 -- front/app/translations/admin/nl-NL.json | 2 -- front/app/translations/admin/pl-PL.json | 2 -- front/app/translations/admin/pt-BR.json | 2 -- front/app/translations/admin/sr-Latn.json | 2 -- front/app/translations/admin/sr-SP.json | 2 -- front/app/translations/admin/sv-SE.json | 2 -- front/app/translations/admin/tr-TR.json | 2 -- front/app/translations/ar-MA.json | 2 -- front/app/translations/ar-SA.json | 2 -- front/app/translations/ca-ES.json | 2 -- front/app/translations/cy-GB.json | 2 -- front/app/translations/da-DK.json | 2 -- front/app/translations/de-DE.json | 2 -- front/app/translations/el-GR.json | 2 -- front/app/translations/en-CA.json | 2 -- front/app/translations/en-GB.json | 2 -- front/app/translations/en-IE.json | 2 -- front/app/translations/en.json | 12 ++++++------ front/app/translations/es-CL.json | 2 -- front/app/translations/es-ES.json | 2 -- front/app/translations/fi-FI.json | 2 -- front/app/translations/fr-BE.json | 2 -- front/app/translations/fr-FR.json | 2 -- front/app/translations/hr-HR.json | 2 -- front/app/translations/it-IT.json | 2 -- front/app/translations/kl-GL.json | 2 -- front/app/translations/lb-LU.json | 2 -- front/app/translations/lv-LV.json | 2 -- front/app/translations/nb-NO.json | 2 -- front/app/translations/nl-BE.json | 2 -- front/app/translations/nl-NL.json | 2 -- front/app/translations/pl-PL.json | 2 -- front/app/translations/pt-BR.json | 2 -- front/app/translations/sr-Latn.json | 2 -- front/app/translations/sr-SP.json | 2 -- front/app/translations/sv-SE.json | 2 -- front/app/translations/tr-TR.json | 2 -- 57 files changed, 8 insertions(+), 118 deletions(-) diff --git a/front/app/translations/admin/ar-SA.json b/front/app/translations/admin/ar-SA.json index 1993841673cb..d4992c524409 100644 --- a/front/app/translations/admin/ar-SA.json +++ b/front/app/translations/admin/ar-SA.json @@ -165,7 +165,6 @@ "app.components.admin.PostManager.components.goToInputManager": "انتقل إلى مدير الإدخال", "app.components.admin.PostManager.components.goToProposalManager": "اذهب إلى مدير الاقتراح", "app.components.admin.PostManager.contributionFormTitle": "تحرير المساهمة", - "app.components.admin.PostManager.cosponsors": "الرعاة", "app.components.admin.PostManager.cost": "يكلف", "app.components.admin.PostManager.currentLat": "دائرة العرض المركزية", "app.components.admin.PostManager.currentLng": "خط الطول المركزي", @@ -752,7 +751,6 @@ "app.containers.Admin.emails.viewExample": "منظر", "app.containers.Admin.ideas.import": "استيراد", "app.containers.Admin.initiatives.addNewProposal": "إضافة مقترح", - "app.containers.Admin.initiatives.cosponsors": "الرعاة", "app.containers.Admin.initiatives.cosponsorsNumberLabel": "عدد المشاركين في الرعاية", "app.containers.Admin.initiatives.cosponsorsNumberMinError1": "يجب أن يكون عدد المشاركين في الرعاية 1 على الأقل.", "app.containers.Admin.initiatives.enableProposals": "تمكين المقترحات", diff --git a/front/app/translations/admin/ca-ES.json b/front/app/translations/admin/ca-ES.json index 796f9dcca90a..5bd54f47495d 100644 --- a/front/app/translations/admin/ca-ES.json +++ b/front/app/translations/admin/ca-ES.json @@ -95,7 +95,6 @@ "app.components.admin.PostManager.components.goToInputManager": "Aneu al gestor d'entrada", "app.components.admin.PostManager.components.goToProposalManager": "Aneu al gestor de propostes", "app.components.admin.PostManager.contributionFormTitle": "Edita la contribució", - "app.components.admin.PostManager.cosponsors": "Copatrocinadors", "app.components.admin.PostManager.cost": "Cost", "app.components.admin.PostManager.currentLat": "Latitud central", "app.components.admin.PostManager.currentLng": "Longitud central", @@ -516,7 +515,6 @@ "app.containers.Admin.emails.viewExample": "Veure", "app.containers.Admin.ideas.import": "Importar", "app.containers.Admin.initiatives.addNewProposal": "Afegir una proposta", - "app.containers.Admin.initiatives.cosponsors": "Copatrocinadors", "app.containers.Admin.initiatives.cosponsorsNumberLabel": "Nombre de copatrocinadors", "app.containers.Admin.initiatives.cosponsorsNumberMinError1": "El nombre de copatrocinadors ha de ser com a mínim 1.", "app.containers.Admin.initiatives.enableProposals": "Habilitar les propostes", diff --git a/front/app/translations/admin/cy-GB.json b/front/app/translations/admin/cy-GB.json index 1796a1b79988..382e8e175d2c 100644 --- a/front/app/translations/admin/cy-GB.json +++ b/front/app/translations/admin/cy-GB.json @@ -165,7 +165,6 @@ "app.components.admin.PostManager.components.goToInputManager": "Ewch i'r rheolwr mewnbwn", "app.components.admin.PostManager.components.goToProposalManager": "Ewch at y rheolwr cynnig", "app.components.admin.PostManager.contributionFormTitle": "Golygu cyfraniad", - "app.components.admin.PostManager.cosponsors": "Cosponwyr", "app.components.admin.PostManager.cost": "Cost", "app.components.admin.PostManager.currentLat": "lledred canol", "app.components.admin.PostManager.currentLng": "Hydred canol", @@ -752,7 +751,6 @@ "app.containers.Admin.emails.viewExample": "Golwg", "app.containers.Admin.ideas.import": "Mewnforio", "app.containers.Admin.initiatives.addNewProposal": "Ychwanegu cynnig", - "app.containers.Admin.initiatives.cosponsors": "Cosponwyr", "app.containers.Admin.initiatives.cosponsorsNumberLabel": "Nifer y gosponwyr", "app.containers.Admin.initiatives.cosponsorsNumberMinError1": "Mae angen i nifer y gosponwyr fod o leiaf 1.", "app.containers.Admin.initiatives.enableProposals": "Galluogi cynigion", diff --git a/front/app/translations/admin/da-DK.json b/front/app/translations/admin/da-DK.json index 984ed1739138..3f90363a889f 100644 --- a/front/app/translations/admin/da-DK.json +++ b/front/app/translations/admin/da-DK.json @@ -165,7 +165,6 @@ "app.components.admin.PostManager.components.goToInputManager": "Gå til input manager", "app.components.admin.PostManager.components.goToProposalManager": "Gå til forslagshåndtering", "app.components.admin.PostManager.contributionFormTitle": "Rediger bidrag", - "app.components.admin.PostManager.cosponsors": "Medstillere", "app.components.admin.PostManager.cost": "Omkostninger", "app.components.admin.PostManager.currentLat": "Centrer breddegrad", "app.components.admin.PostManager.currentLng": "Midterste længdegrad", @@ -752,7 +751,6 @@ "app.containers.Admin.emails.viewExample": "Se", "app.containers.Admin.ideas.import": "Import", "app.containers.Admin.initiatives.addNewProposal": "Tilføj et forslag", - "app.containers.Admin.initiatives.cosponsors": "Medstillere", "app.containers.Admin.initiatives.cosponsorsNumberLabel": "Antal medstillere", "app.containers.Admin.initiatives.cosponsorsNumberMinError1": "Antallet af medstillere skal være mindst 1.", "app.containers.Admin.initiatives.enableProposals": "Aktiver forslag", diff --git a/front/app/translations/admin/de-DE.json b/front/app/translations/admin/de-DE.json index e1f445e82c29..cd1b199c8a1b 100644 --- a/front/app/translations/admin/de-DE.json +++ b/front/app/translations/admin/de-DE.json @@ -165,7 +165,6 @@ "app.components.admin.PostManager.components.goToInputManager": "Zum Beitragsmanager", "app.components.admin.PostManager.components.goToProposalManager": "Zum Vorschlagsmanager", "app.components.admin.PostManager.contributionFormTitle": "Beitrag bearbeiten", - "app.components.admin.PostManager.cosponsors": "Unterstützer*innen", "app.components.admin.PostManager.cost": "Kosten", "app.components.admin.PostManager.currentLat": "Längengrad Mitte", "app.components.admin.PostManager.currentLng": "Längengrad Mitte", @@ -752,7 +751,6 @@ "app.containers.Admin.emails.viewExample": "Vorschau", "app.containers.Admin.ideas.import": "Importieren", "app.containers.Admin.initiatives.addNewProposal": "Einen Vorschlag hinzufügen", - "app.containers.Admin.initiatives.cosponsors": "Unterstützer*innen", "app.containers.Admin.initiatives.cosponsorsNumberLabel": "Anzahl der Unterstützer*innen", "app.containers.Admin.initiatives.cosponsorsNumberMinError1": "Sie müssen mindestens eine*n Unterstützer*in haben.", "app.containers.Admin.initiatives.enableProposals": "Vorschläge aktivieren", diff --git a/front/app/translations/admin/el-GR.json b/front/app/translations/admin/el-GR.json index ca3c21af6241..a6663592aebb 100644 --- a/front/app/translations/admin/el-GR.json +++ b/front/app/translations/admin/el-GR.json @@ -95,7 +95,6 @@ "app.components.admin.PostManager.components.goToInputManager": "Μετάβαση στον διαχειριστή εισόδου", "app.components.admin.PostManager.components.goToProposalManager": "Μετάβαση στον διαχειριστή προτάσεων", "app.components.admin.PostManager.contributionFormTitle": "Επεξεργασία συμβολής", - "app.components.admin.PostManager.cosponsors": "Συνυπογράφοντες", "app.components.admin.PostManager.cost": "Κόστος", "app.components.admin.PostManager.currentLat": "Κεντρικό γεωγραφικό πλάτος", "app.components.admin.PostManager.currentLng": "Κεντρικό γεωγραφικό μήκος", @@ -516,7 +515,6 @@ "app.containers.Admin.emails.viewExample": "Προβολή", "app.containers.Admin.ideas.import": "Εισαγωγή", "app.containers.Admin.initiatives.addNewProposal": "Προσθήκη πρότασης", - "app.containers.Admin.initiatives.cosponsors": "Συνυπογράφοντες", "app.containers.Admin.initiatives.cosponsorsNumberLabel": "Αριθμός συνυποστηρικτών", "app.containers.Admin.initiatives.cosponsorsNumberMinError1": "Ο αριθμός των συνυποστηρικτών πρέπει να είναι τουλάχιστον 1.", "app.containers.Admin.initiatives.enableProposals": "Ενεργοποίηση προτάσεων", diff --git a/front/app/translations/admin/en-CA.json b/front/app/translations/admin/en-CA.json index 61e2a72294f8..5cbb550dbecd 100644 --- a/front/app/translations/admin/en-CA.json +++ b/front/app/translations/admin/en-CA.json @@ -165,7 +165,6 @@ "app.components.admin.PostManager.components.goToInputManager": "Go to input manager", "app.components.admin.PostManager.components.goToProposalManager": "Go to proposal manager", "app.components.admin.PostManager.contributionFormTitle": "Edit contribution", - "app.components.admin.PostManager.cosponsors": "Cosponsors", "app.components.admin.PostManager.cost": "Cost", "app.components.admin.PostManager.currentLat": "Center latitude", "app.components.admin.PostManager.currentLng": "Center longitude", @@ -752,7 +751,6 @@ "app.containers.Admin.emails.viewExample": "View", "app.containers.Admin.ideas.import": "Import", "app.containers.Admin.initiatives.addNewProposal": "Add a proposal", - "app.containers.Admin.initiatives.cosponsors": "Cosponsors", "app.containers.Admin.initiatives.cosponsorsNumberLabel": "Number of cosponsors", "app.containers.Admin.initiatives.cosponsorsNumberMinError1": "The number of cosponsors needs to be at least 1.", "app.containers.Admin.initiatives.enableProposals": "Enable proposals", diff --git a/front/app/translations/admin/en-GB.json b/front/app/translations/admin/en-GB.json index dbcb8b6a72f2..432ca773ed9f 100644 --- a/front/app/translations/admin/en-GB.json +++ b/front/app/translations/admin/en-GB.json @@ -165,7 +165,6 @@ "app.components.admin.PostManager.components.goToInputManager": "Go to input manager", "app.components.admin.PostManager.components.goToProposalManager": "Go to proposal manager", "app.components.admin.PostManager.contributionFormTitle": "Edit contribution", - "app.components.admin.PostManager.cosponsors": "Cosponsors", "app.components.admin.PostManager.cost": "Cost", "app.components.admin.PostManager.currentLat": "Center latitude", "app.components.admin.PostManager.currentLng": "Center longitude", @@ -752,7 +751,6 @@ "app.containers.Admin.emails.viewExample": "View", "app.containers.Admin.ideas.import": "Import", "app.containers.Admin.initiatives.addNewProposal": "{tenantName, select, stirlingcouncil {Add a petition} other {Add a proposal}}", - "app.containers.Admin.initiatives.cosponsors": "Cosponsors", "app.containers.Admin.initiatives.cosponsorsNumberLabel": "Number of cosponsors", "app.containers.Admin.initiatives.cosponsorsNumberMinError1": "The number of cosponsors needs to be at least 1.", "app.containers.Admin.initiatives.enableProposals": "Enable proposals", diff --git a/front/app/translations/admin/en-IE.json b/front/app/translations/admin/en-IE.json index 61e2a72294f8..5cbb550dbecd 100644 --- a/front/app/translations/admin/en-IE.json +++ b/front/app/translations/admin/en-IE.json @@ -165,7 +165,6 @@ "app.components.admin.PostManager.components.goToInputManager": "Go to input manager", "app.components.admin.PostManager.components.goToProposalManager": "Go to proposal manager", "app.components.admin.PostManager.contributionFormTitle": "Edit contribution", - "app.components.admin.PostManager.cosponsors": "Cosponsors", "app.components.admin.PostManager.cost": "Cost", "app.components.admin.PostManager.currentLat": "Center latitude", "app.components.admin.PostManager.currentLng": "Center longitude", @@ -752,7 +751,6 @@ "app.containers.Admin.emails.viewExample": "View", "app.containers.Admin.ideas.import": "Import", "app.containers.Admin.initiatives.addNewProposal": "Add a proposal", - "app.containers.Admin.initiatives.cosponsors": "Cosponsors", "app.containers.Admin.initiatives.cosponsorsNumberLabel": "Number of cosponsors", "app.containers.Admin.initiatives.cosponsorsNumberMinError1": "The number of cosponsors needs to be at least 1.", "app.containers.Admin.initiatives.enableProposals": "Enable proposals", diff --git a/front/app/translations/admin/en.json b/front/app/translations/admin/en.json index 61e2a72294f8..f97419725336 100644 --- a/front/app/translations/admin/en.json +++ b/front/app/translations/admin/en.json @@ -155,6 +155,7 @@ "app.components.admin.PostManager.bodyTitle": "Description", "app.components.admin.PostManager.cancel2": "Cancel", "app.components.admin.PostManager.changeStatusModalTitle": "Change this proposal's status", + "app.components.admin.PostManager.co-sponsors": "Co-sponsors", "app.components.admin.PostManager.comments": "Comments", "app.components.admin.PostManager.components.ActionBar.deleteInitiativesExplanation": "This means you will lose all data associated with these initiatives, like comments and votes. This action cannot be undone.", "app.components.admin.PostManager.components.ActionBar.deleteInitiativesTitle": "Are you sure you want to delete these initiatives?", @@ -165,7 +166,6 @@ "app.components.admin.PostManager.components.goToInputManager": "Go to input manager", "app.components.admin.PostManager.components.goToProposalManager": "Go to proposal manager", "app.components.admin.PostManager.contributionFormTitle": "Edit contribution", - "app.components.admin.PostManager.cosponsors": "Cosponsors", "app.components.admin.PostManager.cost": "Cost", "app.components.admin.PostManager.currentLat": "Center latitude", "app.components.admin.PostManager.currentLng": "Center longitude", @@ -752,7 +752,7 @@ "app.containers.Admin.emails.viewExample": "View", "app.containers.Admin.ideas.import": "Import", "app.containers.Admin.initiatives.addNewProposal": "Add a proposal", - "app.containers.Admin.initiatives.cosponsors": "Cosponsors", + "app.containers.Admin.initiatives.co-sponsors": "Co-sponsors", "app.containers.Admin.initiatives.cosponsorsNumberLabel": "Number of cosponsors", "app.containers.Admin.initiatives.cosponsorsNumberMinError1": "The number of cosponsors needs to be at least 1.", "app.containers.Admin.initiatives.enableProposals": "Enable proposals", diff --git a/front/app/translations/admin/es-CL.json b/front/app/translations/admin/es-CL.json index 609c2f991600..17e68b4fd03b 100644 --- a/front/app/translations/admin/es-CL.json +++ b/front/app/translations/admin/es-CL.json @@ -165,7 +165,6 @@ "app.components.admin.PostManager.components.goToInputManager": "Ir al gestor de aportes", "app.components.admin.PostManager.components.goToProposalManager": "Ir al gestor de propuestas", "app.components.admin.PostManager.contributionFormTitle": "Editar contribución", - "app.components.admin.PostManager.cosponsors": "Copatrocinadores", "app.components.admin.PostManager.cost": "Coste", "app.components.admin.PostManager.currentLat": "Latitud actual", "app.components.admin.PostManager.currentLng": "Longitud actual", @@ -752,7 +751,6 @@ "app.containers.Admin.emails.viewExample": "Ver", "app.containers.Admin.ideas.import": "Importar", "app.containers.Admin.initiatives.addNewProposal": "Añadir una propuesta", - "app.containers.Admin.initiatives.cosponsors": "Copatrocinadores", "app.containers.Admin.initiatives.cosponsorsNumberLabel": "Número de copatrocinadores", "app.containers.Admin.initiatives.cosponsorsNumberMinError1": "El número de copatrocinadores debe ser de al menos 1.", "app.containers.Admin.initiatives.enableProposals": "Habilita las propuestas", diff --git a/front/app/translations/admin/es-ES.json b/front/app/translations/admin/es-ES.json index 63606c82bc25..1529ba4dc390 100644 --- a/front/app/translations/admin/es-ES.json +++ b/front/app/translations/admin/es-ES.json @@ -165,7 +165,6 @@ "app.components.admin.PostManager.components.goToInputManager": "Ir al gestor de aportes", "app.components.admin.PostManager.components.goToProposalManager": "Ir al gestor de propuestas", "app.components.admin.PostManager.contributionFormTitle": "Editar contribución", - "app.components.admin.PostManager.cosponsors": "Copatrocinadores", "app.components.admin.PostManager.cost": "Coste", "app.components.admin.PostManager.currentLat": "Latitud actual", "app.components.admin.PostManager.currentLng": "Longitud actual", @@ -752,7 +751,6 @@ "app.containers.Admin.emails.viewExample": "Ver", "app.containers.Admin.ideas.import": "Importar", "app.containers.Admin.initiatives.addNewProposal": "Añadir una propuesta", - "app.containers.Admin.initiatives.cosponsors": "Copatrocinadores", "app.containers.Admin.initiatives.cosponsorsNumberLabel": "Número de copatrocinadores", "app.containers.Admin.initiatives.cosponsorsNumberMinError1": "El número de copatrocinadores debe ser al menos 1.", "app.containers.Admin.initiatives.enableProposals": "Habilitar propuestas", diff --git a/front/app/translations/admin/fi-FI.json b/front/app/translations/admin/fi-FI.json index 21998facc059..9f1eb4fd4500 100644 --- a/front/app/translations/admin/fi-FI.json +++ b/front/app/translations/admin/fi-FI.json @@ -165,7 +165,6 @@ "app.components.admin.PostManager.components.goToInputManager": "Siirry syötteiden hallintaan", "app.components.admin.PostManager.components.goToProposalManager": "Siirry ehdotusten hallintaan", "app.components.admin.PostManager.contributionFormTitle": "Muokkaa panosta", - "app.components.admin.PostManager.cosponsors": "Kannattajat", "app.components.admin.PostManager.cost": "Kustannus", "app.components.admin.PostManager.currentLat": "Keskileveysaste", "app.components.admin.PostManager.currentLng": "Keskipituusaste", @@ -752,7 +751,6 @@ "app.containers.Admin.emails.viewExample": "Näytä", "app.containers.Admin.ideas.import": "Tuonti", "app.containers.Admin.initiatives.addNewProposal": "Lisää ehdotus", - "app.containers.Admin.initiatives.cosponsors": "Kannattajat", "app.containers.Admin.initiatives.cosponsorsNumberLabel": "Kannattajien määrä", "app.containers.Admin.initiatives.cosponsorsNumberMinError1": "Kannattajien lukumäärän on oltava vähintään 1.", "app.containers.Admin.initiatives.enableProposals": "Ota ehdotukset käyttöön", diff --git a/front/app/translations/admin/fr-BE.json b/front/app/translations/admin/fr-BE.json index da2287fb39f0..ed4a57619cf2 100644 --- a/front/app/translations/admin/fr-BE.json +++ b/front/app/translations/admin/fr-BE.json @@ -165,7 +165,6 @@ "app.components.admin.PostManager.components.goToInputManager": "Aller dans le gestionnaire de contributions", "app.components.admin.PostManager.components.goToProposalManager": "Aller dans le gestionnaire de propositions", "app.components.admin.PostManager.contributionFormTitle": "Modifiez la suggestion", - "app.components.admin.PostManager.cosponsors": "Soutiens", "app.components.admin.PostManager.cost": "Coût", "app.components.admin.PostManager.currentLat": "Latitude par défaut", "app.components.admin.PostManager.currentLng": "Longitude par défaut", @@ -752,7 +751,6 @@ "app.containers.Admin.emails.viewExample": "Voir", "app.containers.Admin.ideas.import": "Importer", "app.containers.Admin.initiatives.addNewProposal": "Ajouter une proposition", - "app.containers.Admin.initiatives.cosponsors": "Soutiens", "app.containers.Admin.initiatives.cosponsorsNumberLabel": "Nombre de soutiens", "app.containers.Admin.initiatives.cosponsorsNumberMinError1": "Le nombre de soutiens doit être au moins 1.", "app.containers.Admin.initiatives.enableProposals": "Activer les propositions", diff --git a/front/app/translations/admin/fr-FR.json b/front/app/translations/admin/fr-FR.json index 6d71d1a0a4ae..58e1b282ec3e 100644 --- a/front/app/translations/admin/fr-FR.json +++ b/front/app/translations/admin/fr-FR.json @@ -165,7 +165,6 @@ "app.components.admin.PostManager.components.goToInputManager": "Aller dans le gestionnaire de contributions", "app.components.admin.PostManager.components.goToProposalManager": "Aller dans le gestionnaire de propositions", "app.components.admin.PostManager.contributionFormTitle": "Modifiez la suggestion", - "app.components.admin.PostManager.cosponsors": "Soutiens", "app.components.admin.PostManager.cost": "Coût", "app.components.admin.PostManager.currentLat": "Latitude par défaut", "app.components.admin.PostManager.currentLng": "Longitude par défaut", @@ -752,7 +751,6 @@ "app.containers.Admin.emails.viewExample": "Voir", "app.containers.Admin.ideas.import": "Importer", "app.containers.Admin.initiatives.addNewProposal": "Ajouter une proposition", - "app.containers.Admin.initiatives.cosponsors": "Soutiens", "app.containers.Admin.initiatives.cosponsorsNumberLabel": "Nombre de soutiens", "app.containers.Admin.initiatives.cosponsorsNumberMinError1": "Le nombre de soutiens doit être au moins 1.", "app.containers.Admin.initiatives.enableProposals": "Activer les propositions", diff --git a/front/app/translations/admin/hr-HR.json b/front/app/translations/admin/hr-HR.json index 666b8c8216ad..5f0fd79e4bce 100644 --- a/front/app/translations/admin/hr-HR.json +++ b/front/app/translations/admin/hr-HR.json @@ -165,7 +165,6 @@ "app.components.admin.PostManager.components.goToInputManager": "Idite na upravitelj unosa", "app.components.admin.PostManager.components.goToProposalManager": "Idite do upravitelja ponuda", "app.components.admin.PostManager.contributionFormTitle": "Uredi doprinos", - "app.components.admin.PostManager.cosponsors": "Kosponzori", "app.components.admin.PostManager.cost": "trošak", "app.components.admin.PostManager.currentLat": "Središnja geografska širina", "app.components.admin.PostManager.currentLng": "Središnja geografska duljina", @@ -752,7 +751,6 @@ "app.containers.Admin.emails.viewExample": "Pogled", "app.containers.Admin.ideas.import": "Uvoz", "app.containers.Admin.initiatives.addNewProposal": "Dodajte prijedlog", - "app.containers.Admin.initiatives.cosponsors": "Kosponzori", "app.containers.Admin.initiatives.cosponsorsNumberLabel": "Broj kosponzora", "app.containers.Admin.initiatives.cosponsorsNumberMinError1": "Broj kosponzora mora biti najmanje 1.", "app.containers.Admin.initiatives.enableProposals": "Omogući prijedloge", diff --git a/front/app/translations/admin/it-IT.json b/front/app/translations/admin/it-IT.json index 7315c033b757..dafdc71ef19c 100644 --- a/front/app/translations/admin/it-IT.json +++ b/front/app/translations/admin/it-IT.json @@ -95,7 +95,6 @@ "app.components.admin.PostManager.components.goToInputManager": "Vai al gestore degli input", "app.components.admin.PostManager.components.goToProposalManager": "Vai al gestore delle proposte", "app.components.admin.PostManager.contributionFormTitle": "Modifica del contributo", - "app.components.admin.PostManager.cosponsors": "Cosponsor", "app.components.admin.PostManager.cost": "Costo", "app.components.admin.PostManager.currentLat": "Latitudine del centro", "app.components.admin.PostManager.currentLng": "Longitudine del centro", @@ -516,7 +515,6 @@ "app.containers.Admin.emails.viewExample": "Guarda", "app.containers.Admin.ideas.import": "Import", "app.containers.Admin.initiatives.addNewProposal": "Add a proposal", - "app.containers.Admin.initiatives.cosponsors": "Cosponsor", "app.containers.Admin.initiatives.cosponsorsNumberLabel": "Numero di cosponsor", "app.containers.Admin.initiatives.cosponsorsNumberMinError1": "Il numero di cosponsor deve essere almeno pari a 1.", "app.containers.Admin.initiatives.enableProposals": "Abilita proposte", diff --git a/front/app/translations/admin/lv-LV.json b/front/app/translations/admin/lv-LV.json index dc5b8ebe8c95..e87e14bd829f 100644 --- a/front/app/translations/admin/lv-LV.json +++ b/front/app/translations/admin/lv-LV.json @@ -165,7 +165,6 @@ "app.components.admin.PostManager.components.goToInputManager": "Iet uz ievades pārvaldnieku", "app.components.admin.PostManager.components.goToProposalManager": "Pārejiet uz priekšlikumu pārvaldnieku", "app.components.admin.PostManager.contributionFormTitle": "Rediģēt ieguldījumu", - "app.components.admin.PostManager.cosponsors": "Atbalstītāji", "app.components.admin.PostManager.cost": "Izmaksas", "app.components.admin.PostManager.currentLat": "Ģeogrāfiskā platuma viduspunkts", "app.components.admin.PostManager.currentLng": "Ģeogrāfiskā garuma viduspunkts", @@ -752,7 +751,6 @@ "app.containers.Admin.emails.viewExample": "Skatīt", "app.containers.Admin.ideas.import": "Importēt", "app.containers.Admin.initiatives.addNewProposal": "Pievienot priekšlikumu", - "app.containers.Admin.initiatives.cosponsors": "Atbalstītāji", "app.containers.Admin.initiatives.cosponsorsNumberLabel": "Atbalstītāju skaits", "app.containers.Admin.initiatives.cosponsorsNumberMinError1": "Atbalstītāju skaitam jābūt vismaz 1.", "app.containers.Admin.initiatives.enableProposals": "Iespēja iesniegt priekšlikumus", diff --git a/front/app/translations/admin/nb-NO.json b/front/app/translations/admin/nb-NO.json index 908fbcef9d36..3f9b9561e032 100644 --- a/front/app/translations/admin/nb-NO.json +++ b/front/app/translations/admin/nb-NO.json @@ -165,7 +165,6 @@ "app.components.admin.PostManager.components.goToInputManager": "Gå til input manager", "app.components.admin.PostManager.components.goToProposalManager": "Gå til forslagsansvarlig", "app.components.admin.PostManager.contributionFormTitle": "Rediger bidrag", - "app.components.admin.PostManager.cosponsors": "Medsponsorer", "app.components.admin.PostManager.cost": "Koste", "app.components.admin.PostManager.currentLat": "Midtre breddegrad", "app.components.admin.PostManager.currentLng": "Midtre lengdegrad", @@ -752,7 +751,6 @@ "app.containers.Admin.emails.viewExample": "Vis", "app.containers.Admin.ideas.import": "Importer", "app.containers.Admin.initiatives.addNewProposal": "Legg til et forslag", - "app.containers.Admin.initiatives.cosponsors": "Medsponsorer", "app.containers.Admin.initiatives.cosponsorsNumberLabel": "Antall medsponsorer", "app.containers.Admin.initiatives.cosponsorsNumberMinError1": "Antall medsponsorer må være minst 1.", "app.containers.Admin.initiatives.enableProposals": "Aktiver forslag", diff --git a/front/app/translations/admin/nl-BE.json b/front/app/translations/admin/nl-BE.json index 08ad137f9b10..56fc9ef59c74 100644 --- a/front/app/translations/admin/nl-BE.json +++ b/front/app/translations/admin/nl-BE.json @@ -165,7 +165,6 @@ "app.components.admin.PostManager.components.goToInputManager": "Ga naar beheer bijdragen", "app.components.admin.PostManager.components.goToProposalManager": "Ga naar voorstellenbeheer", "app.components.admin.PostManager.contributionFormTitle": "Bijdrage bewerken", - "app.components.admin.PostManager.cosponsors": "Ondersteuners", "app.components.admin.PostManager.cost": "Kosten", "app.components.admin.PostManager.currentLat": "Huidige breedtegraad", "app.components.admin.PostManager.currentLng": "Huidige lengtegraad", @@ -752,7 +751,6 @@ "app.containers.Admin.emails.viewExample": "Bekijk", "app.containers.Admin.ideas.import": "Importeren", "app.containers.Admin.initiatives.addNewProposal": "Een voorstel toevoegen", - "app.containers.Admin.initiatives.cosponsors": "Ondersteuners", "app.containers.Admin.initiatives.cosponsorsNumberLabel": "Aantal ondersteuners", "app.containers.Admin.initiatives.cosponsorsNumberMinError1": "Het aantal ondersteuners moet minstens 1 zijn.", "app.containers.Admin.initiatives.enableProposals": "Voorstellen inschakelen", diff --git a/front/app/translations/admin/nl-NL.json b/front/app/translations/admin/nl-NL.json index 0a9d19799bc3..27c18ea989f8 100644 --- a/front/app/translations/admin/nl-NL.json +++ b/front/app/translations/admin/nl-NL.json @@ -165,7 +165,6 @@ "app.components.admin.PostManager.components.goToInputManager": "Ga naar beheer bijdragen", "app.components.admin.PostManager.components.goToProposalManager": "Ga naar voorstellenbeheer", "app.components.admin.PostManager.contributionFormTitle": "Bijdrage bewerken", - "app.components.admin.PostManager.cosponsors": "Ondersteuners", "app.components.admin.PostManager.cost": "Kosten", "app.components.admin.PostManager.currentLat": "Huidige breedtegraad", "app.components.admin.PostManager.currentLng": "Huidige lengtegraad", @@ -752,7 +751,6 @@ "app.containers.Admin.emails.viewExample": "Bekijk", "app.containers.Admin.ideas.import": "Importeren", "app.containers.Admin.initiatives.addNewProposal": "Een voorstel toevoegen", - "app.containers.Admin.initiatives.cosponsors": "Ondersteuners", "app.containers.Admin.initiatives.cosponsorsNumberLabel": "Aantal ondersteuners", "app.containers.Admin.initiatives.cosponsorsNumberMinError1": "Het aantal ondersteuners moet minstens 1 zijn.", "app.containers.Admin.initiatives.enableProposals": "Voorstellen inschakelen", diff --git a/front/app/translations/admin/pl-PL.json b/front/app/translations/admin/pl-PL.json index 899a7e2f2dde..0fb1d70fcb0e 100644 --- a/front/app/translations/admin/pl-PL.json +++ b/front/app/translations/admin/pl-PL.json @@ -165,7 +165,6 @@ "app.components.admin.PostManager.components.goToInputManager": "Przejdź do menedżera wprowadzania danych", "app.components.admin.PostManager.components.goToProposalManager": "Przejdź do menedżera propozycji", "app.components.admin.PostManager.contributionFormTitle": "Edycja wkładu", - "app.components.admin.PostManager.cosponsors": "Współsponsorzy", "app.components.admin.PostManager.cost": "Koszt", "app.components.admin.PostManager.currentLat": "Aktualna szerokość geograficzna", "app.components.admin.PostManager.currentLng": "Aktualna długość geograficzna", @@ -752,7 +751,6 @@ "app.containers.Admin.emails.viewExample": "Zobacz", "app.containers.Admin.ideas.import": "Import", "app.containers.Admin.initiatives.addNewProposal": "Dodaj propozycję", - "app.containers.Admin.initiatives.cosponsors": "Współsponsorzy", "app.containers.Admin.initiatives.cosponsorsNumberLabel": "Liczba współwnioskodawców", "app.containers.Admin.initiatives.cosponsorsNumberMinError1": "Liczba współwnioskodawców musi wynosić co najmniej 1.", "app.containers.Admin.initiatives.enableProposals": "Włącz oddolne propozycje", diff --git a/front/app/translations/admin/pt-BR.json b/front/app/translations/admin/pt-BR.json index 24c81d4b2736..4eb17e14f6f3 100644 --- a/front/app/translations/admin/pt-BR.json +++ b/front/app/translations/admin/pt-BR.json @@ -165,7 +165,6 @@ "app.components.admin.PostManager.components.goToInputManager": "Ir para o gerenciador de entrada", "app.components.admin.PostManager.components.goToProposalManager": "Ir para o gerenciador de propostas", "app.components.admin.PostManager.contributionFormTitle": "Editar contribuição", - "app.components.admin.PostManager.cosponsors": "Co-patrocinadores", "app.components.admin.PostManager.cost": "Custo", "app.components.admin.PostManager.currentLat": "Latitude atual", "app.components.admin.PostManager.currentLng": "Longitude atual", @@ -752,7 +751,6 @@ "app.containers.Admin.emails.viewExample": "Visualizar", "app.containers.Admin.ideas.import": "Importar", "app.containers.Admin.initiatives.addNewProposal": "Adicione uma proposta", - "app.containers.Admin.initiatives.cosponsors": "Co-patrocinadores", "app.containers.Admin.initiatives.cosponsorsNumberLabel": "Número de co-patrocinadores", "app.containers.Admin.initiatives.cosponsorsNumberMinError1": "O número de co-patrocinadores tem de ser, pelo menos, 1.", "app.containers.Admin.initiatives.enableProposals": "Habilitar propostas", diff --git a/front/app/translations/admin/sr-Latn.json b/front/app/translations/admin/sr-Latn.json index 0d62fdba7711..0d77f1f0b4be 100644 --- a/front/app/translations/admin/sr-Latn.json +++ b/front/app/translations/admin/sr-Latn.json @@ -165,7 +165,6 @@ "app.components.admin.PostManager.components.goToInputManager": "Идите на менаџер уноса", "app.components.admin.PostManager.components.goToProposalManager": "Идите до менаџера предлога", "app.components.admin.PostManager.contributionFormTitle": "Уредите допринос", - "app.components.admin.PostManager.cosponsors": "Cosponsors", "app.components.admin.PostManager.cost": "Cost", "app.components.admin.PostManager.currentLat": "Centralna širina", "app.components.admin.PostManager.currentLng": "Centralna dužina", @@ -752,7 +751,6 @@ "app.containers.Admin.emails.viewExample": "Поглед", "app.containers.Admin.ideas.import": "Uvezi", "app.containers.Admin.initiatives.addNewProposal": "Dodajte predlog", - "app.containers.Admin.initiatives.cosponsors": "Cosponsors", "app.containers.Admin.initiatives.cosponsorsNumberLabel": "Number of cosponsors", "app.containers.Admin.initiatives.cosponsorsNumberMinError1": "The number of cosponsors needs to be at least 1.", "app.containers.Admin.initiatives.enableProposals": "Omogući ponude", diff --git a/front/app/translations/admin/sr-SP.json b/front/app/translations/admin/sr-SP.json index dbdeee680f31..340be69a78b5 100644 --- a/front/app/translations/admin/sr-SP.json +++ b/front/app/translations/admin/sr-SP.json @@ -165,7 +165,6 @@ "app.components.admin.PostManager.components.goToInputManager": "Идите на менаџер уноса", "app.components.admin.PostManager.components.goToProposalManager": "Идите до менаџера предлога", "app.components.admin.PostManager.contributionFormTitle": "Уреди допринос", - "app.components.admin.PostManager.cosponsors": "Цоспонсорс", "app.components.admin.PostManager.cost": "Цост", "app.components.admin.PostManager.currentLat": "Централна ширина", "app.components.admin.PostManager.currentLng": "Централна географска дужина", @@ -752,7 +751,6 @@ "app.containers.Admin.emails.viewExample": "Поглед", "app.containers.Admin.ideas.import": "Увоз", "app.containers.Admin.initiatives.addNewProposal": "Додајте предлог", - "app.containers.Admin.initiatives.cosponsors": "Цоспонсорс", "app.containers.Admin.initiatives.cosponsorsNumberLabel": "Број коспонзора", "app.containers.Admin.initiatives.cosponsorsNumberMinError1": "Број коспонзора треба да буде најмање 1.", "app.containers.Admin.initiatives.enableProposals": "Омогући предлоге", diff --git a/front/app/translations/admin/sv-SE.json b/front/app/translations/admin/sv-SE.json index 616b54262c8c..dee2552a6e7d 100644 --- a/front/app/translations/admin/sv-SE.json +++ b/front/app/translations/admin/sv-SE.json @@ -165,7 +165,6 @@ "app.components.admin.PostManager.components.goToInputManager": "Gå till inmatningshanteraren", "app.components.admin.PostManager.components.goToProposalManager": "Gå till förslagshanteraren", "app.components.admin.PostManager.contributionFormTitle": "Redigera bidrag", - "app.components.admin.PostManager.cosponsors": "Medförslagsställare", "app.components.admin.PostManager.cost": "Kostnad", "app.components.admin.PostManager.currentLat": "Central latitud", "app.components.admin.PostManager.currentLng": "Central longitud", @@ -752,7 +751,6 @@ "app.containers.Admin.emails.viewExample": "Utsikt", "app.containers.Admin.ideas.import": "Importera", "app.containers.Admin.initiatives.addNewProposal": "Lägg till ett förslag", - "app.containers.Admin.initiatives.cosponsors": "Medförslagsställare", "app.containers.Admin.initiatives.cosponsorsNumberLabel": "Antal medförslagsställare", "app.containers.Admin.initiatives.cosponsorsNumberMinError1": "Antalet medförslagsställare måste vara minst 1.", "app.containers.Admin.initiatives.enableProposals": "Aktivera förslag", diff --git a/front/app/translations/admin/tr-TR.json b/front/app/translations/admin/tr-TR.json index fb1c9a996078..f09ef770c503 100644 --- a/front/app/translations/admin/tr-TR.json +++ b/front/app/translations/admin/tr-TR.json @@ -165,7 +165,6 @@ "app.components.admin.PostManager.components.goToInputManager": "Giriş yöneticisine git", "app.components.admin.PostManager.components.goToProposalManager": "Teklif yöneticisine git", "app.components.admin.PostManager.contributionFormTitle": "Katkıyı düzenle", - "app.components.admin.PostManager.cosponsors": "Eş Sponsorlar", "app.components.admin.PostManager.cost": "Maliyet", "app.components.admin.PostManager.currentLat": "Enlemi ortala", "app.components.admin.PostManager.currentLng": "Boylamı ortala", @@ -752,7 +751,6 @@ "app.containers.Admin.emails.viewExample": "Görünüm", "app.containers.Admin.ideas.import": "İçe aktar", "app.containers.Admin.initiatives.addNewProposal": "Bir öneri ekleyin", - "app.containers.Admin.initiatives.cosponsors": "Eş Sponsorlar", "app.containers.Admin.initiatives.cosponsorsNumberLabel": "Destekçi sayısı", "app.containers.Admin.initiatives.cosponsorsNumberMinError1": "Eş sponsor sayısının en az 1 olması gerekmektedir.", "app.containers.Admin.initiatives.enableProposals": "Teklifleri etkinleştirin", diff --git a/front/app/translations/ar-MA.json b/front/app/translations/ar-MA.json index 15ee20cb7493..4e41a4e99222 100644 --- a/front/app/translations/ar-MA.json +++ b/front/app/translations/ar-MA.json @@ -235,11 +235,9 @@ "app.components.InitiativeCards.xInitiatives": "{initiativesCount, plural, one {# مُقترح} other {# مُقترحات}}", "app.components.InitiativeForm.bannerUploadLabel": "أضِف لافتة", "app.components.InitiativeForm.bannerUploadLabelSubtext": "اجعل صفحتك أكثر جاذبية. ستظهر هذه الصورة في أعلى صفحتك.", - "app.components.InitiativeForm.cosponsorSectionTitle": "يلزم وجود رعاة للمراجعة", "app.components.InitiativeForm.cosponsorSubtextBeforeInput": "يجب أن يكون لديك {noOfCosponsorsText} على الأقل في اقتراحك. قم بدعوة المشاركين في الرعاية من خلال الحقل أدناه. سيتلقى الراعي (الشركاء) المدعوون رسالة بريد إلكتروني.", "app.components.InitiativeForm.cosponsorSubtextBeforeInputNote": "يحتاج المشاركون في رعايتك إلى حساب على موقع الويب هذا قبل ظهورهم في هذه القائمة.", "app.components.InitiativeForm.cosponsorsEmptyError": "يرجى إضافة العدد المطلوب من الجهات الراعية", - "app.components.InitiativeForm.cosponsorsLabel": "الرعاة", "app.components.InitiativeForm.cosponsorsMaxError": "يمكنك فقط إضافة {maxNumberOfCosponsors} رعاة", "app.components.InitiativeForm.cosponsorsPlaceholder": "ابدأ في كتابة اسم للبحث", "app.components.InitiativeForm.descriptionBodyLengthError": "يجب ألا يقل الوصف عن 30 حرفًا", diff --git a/front/app/translations/ar-SA.json b/front/app/translations/ar-SA.json index a25d2f1474c4..22cf6a909c0b 100644 --- a/front/app/translations/ar-SA.json +++ b/front/app/translations/ar-SA.json @@ -235,11 +235,9 @@ "app.components.InitiativeCards.xInitiatives": "{initiativesCount, plural, one {# مُقترح} other {# مُقترحات}}", "app.components.InitiativeForm.bannerUploadLabel": "أضِف لافتة", "app.components.InitiativeForm.bannerUploadLabelSubtext": "اجعل صفحتك أكثر جاذبية. ستظهر هذه الصورة في أعلى صفحتك.", - "app.components.InitiativeForm.cosponsorSectionTitle": "يلزم وجود رعاة للمراجعة", "app.components.InitiativeForm.cosponsorSubtextBeforeInput": "يجب أن يكون لديك {noOfCosponsorsText} على الأقل في اقتراحك. قم بدعوة المشاركين في الرعاية من خلال الحقل أدناه. سيتلقى الراعي (الشركاء) المدعوون رسالة بريد إلكتروني.", "app.components.InitiativeForm.cosponsorSubtextBeforeInputNote": "يحتاج المشاركون في رعايتك إلى حساب على موقع الويب هذا قبل ظهورهم في هذه القائمة.", "app.components.InitiativeForm.cosponsorsEmptyError": "يرجى إضافة العدد المطلوب من الجهات الراعية", - "app.components.InitiativeForm.cosponsorsLabel": "الرعاة", "app.components.InitiativeForm.cosponsorsMaxError": "يمكنك فقط إضافة {maxNumberOfCosponsors} رعاة", "app.components.InitiativeForm.cosponsorsPlaceholder": "ابدأ في كتابة اسم للبحث", "app.components.InitiativeForm.descriptionBodyLengthError": "يجب ألا يقل الوصف عن 30 حرفًا", diff --git a/front/app/translations/ca-ES.json b/front/app/translations/ca-ES.json index ea1b6af53439..f1150544102b 100644 --- a/front/app/translations/ca-ES.json +++ b/front/app/translations/ca-ES.json @@ -235,11 +235,9 @@ "app.components.InitiativeCards.xInitiatives": "{initiativesCount, plural, one {# proposta} other {# propostes}}", "app.components.InitiativeForm.bannerUploadLabel": "Afegir un bàner", "app.components.InitiativeForm.bannerUploadLabelSubtext": "Feu que la vostra pàgina sigui visualment més atractiva. Aquesta imatge es mostrarà a la part superior de la vostra pàgina.", - "app.components.InitiativeForm.cosponsorSectionTitle": "Es necessiten copatrocinadors per a la revisió", "app.components.InitiativeForm.cosponsorSubtextBeforeInput": "Cal que tingueu com a mínim {noOfCosponsorsText} a la vostra proposta. Convida copatrocinadors a través del camp següent. Els copatrocinadors convidats rebran un correu electrònic.", "app.components.InitiativeForm.cosponsorSubtextBeforeInputNote": "Els vostres copatrocinadors necessiten un compte en aquest lloc web abans d'aparèixer en aquesta llista.", "app.components.InitiativeForm.cosponsorsEmptyError": "Si us plau, afegiu el nombre necessari de copatrocinadors", - "app.components.InitiativeForm.cosponsorsLabel": "Copatrocinadors", "app.components.InitiativeForm.cosponsorsMaxError": "Només podeu afegir {maxNumberOfCosponsors} copatrocinadors", "app.components.InitiativeForm.cosponsorsPlaceholder": "Comenceu a escriure un nom per cercar", "app.components.InitiativeForm.descriptionBodyLengthError": "La descripció ha de tenir almenys 30 caràcters", diff --git a/front/app/translations/cy-GB.json b/front/app/translations/cy-GB.json index c427953bdddf..97272f4aab96 100644 --- a/front/app/translations/cy-GB.json +++ b/front/app/translations/cy-GB.json @@ -235,11 +235,9 @@ "app.components.InitiativeCards.xInitiatives": "{initiativesCount, plural, one {# cynnig} other {# cynnig}}", "app.components.InitiativeForm.bannerUploadLabel": "Ychwanegu baner", "app.components.InitiativeForm.bannerUploadLabelSubtext": "Gwnewch eich tudalen yn fwy deniadol yn weledol. Bydd y ddelwedd hon yn cael ei dangos ar ben eich tudalen.", - "app.components.InitiativeForm.cosponsorSectionTitle": "Angen cysyddion ar gyfer adolygiad", "app.components.InitiativeForm.cosponsorSubtextBeforeInput": "Mae'n ofynnol bod gennych o leiaf {noOfCosponsorsText} ar eich cynnig. Gwahoddwch noddwyr drwy'r maes isod. Bydd y cefnogwr(wyr) gwadd yn derbyn e-bost.", "app.components.InitiativeForm.cosponsorSubtextBeforeInputNote": "Mae angen cyfrif ar eich cwsmeriaid ar y wefan hon cyn iddynt ymddangos yn y rhestr hon.", "app.components.InitiativeForm.cosponsorsEmptyError": "Ychwanegwch y nifer gofynnol o gosponwyr", - "app.components.InitiativeForm.cosponsorsLabel": "Cosponwyr", "app.components.InitiativeForm.cosponsorsMaxError": "Dim ond {maxNumberOfCosponsors} gosponsors y gallwch chi eu hychwanegu", "app.components.InitiativeForm.cosponsorsPlaceholder": "Dechreuwch deipio enw i'w chwilio", "app.components.InitiativeForm.descriptionBodyLengthError": "Rhaid i'r disgrifiad fod o leiaf 30 nod", diff --git a/front/app/translations/da-DK.json b/front/app/translations/da-DK.json index d94d5e5521f1..db75940aa0c3 100644 --- a/front/app/translations/da-DK.json +++ b/front/app/translations/da-DK.json @@ -235,11 +235,9 @@ "app.components.InitiativeCards.xInitiatives": "{initiativesCount, plural, one {# forslag} other {# forslag}}", "app.components.InitiativeForm.bannerUploadLabel": "Tilføj et banner", "app.components.InitiativeForm.bannerUploadLabelSubtext": "Gør din side mere visuelt tiltalende. Dette billede vises øverst på din side.", - "app.components.InitiativeForm.cosponsorSectionTitle": "Der er brug for medstillere til gennemgang", "app.components.InitiativeForm.cosponsorSubtextBeforeInput": "Det er påkrævet, at du har mindst {noOfCosponsorsText} på dit forslag. Inviter medstillere via feltet nedenfor. De(n) inviterede medstiller(e) vil modtage en e-mail.", "app.components.InitiativeForm.cosponsorSubtextBeforeInputNote": "Dine medstillere skal have en konto på platformen, før de vises på denne liste.", "app.components.InitiativeForm.cosponsorsEmptyError": "Tilføj venligst det nødvendige antal medstillere", - "app.components.InitiativeForm.cosponsorsLabel": "Medstillere", "app.components.InitiativeForm.cosponsorsMaxError": "Du kan maximum invitere {maxNumberOfCosponsors} medstillere", "app.components.InitiativeForm.cosponsorsPlaceholder": "Begynd at skrive et navn for at søge", "app.components.InitiativeForm.descriptionBodyLengthError": "Beskrivelsen af forslaget skal være mindst 30 tegn lang", diff --git a/front/app/translations/de-DE.json b/front/app/translations/de-DE.json index dcf6b555fea8..8922af4ae9f4 100644 --- a/front/app/translations/de-DE.json +++ b/front/app/translations/de-DE.json @@ -235,11 +235,9 @@ "app.components.InitiativeCards.xInitiatives": "{initiativesCount, plural, no {# Vorschläge} eine {# Vorschlag} other {# Vorschläge}}", "app.components.InitiativeForm.bannerUploadLabel": "Banner hinzufügen", "app.components.InitiativeForm.bannerUploadLabelSubtext": "Gestalten Sie Ihre Seite visuell ansprechender. Dieses Bild wird oben auf Ihrer Seite angezeigt.", - "app.components.InitiativeForm.cosponsorSectionTitle": "Unterstützer*innen für die Überprüfung benötigt", "app.components.InitiativeForm.cosponsorSubtextBeforeInput": "Es ist erforderlich, dass Sie mindestens {noOfCosponsorsText} für Ihren Vorschlag haben. Laden Sie Unterstützer*innen über das unten stehende Feld ein. Die eingeladenen Unterstützer*innen werden eine E-Mail erhalten.", "app.components.InitiativeForm.cosponsorSubtextBeforeInputNote": "Ihre Unterstützer*innen benötigen ein Konto auf dieser Website, damit sie in dieser Liste angezeigt werden können.", "app.components.InitiativeForm.cosponsorsEmptyError": "Bitte fügen Sie die erforderliche Anzahl von Unterstützer*innen hinzu", - "app.components.InitiativeForm.cosponsorsLabel": "Unterstützer*innen", "app.components.InitiativeForm.cosponsorsMaxError": "Sie können nur maximal {maxNumberOfCosponsors} Unterstützer*innen hinzufügen", "app.components.InitiativeForm.cosponsorsPlaceholder": "Einen Namen eingeben, um die Suche zu starten", "app.components.InitiativeForm.descriptionBodyLengthError": "Die Beschreibung muss mindestens 30 Zeichen lang sein", diff --git a/front/app/translations/el-GR.json b/front/app/translations/el-GR.json index e62ac9e2e679..940b8fca8f28 100644 --- a/front/app/translations/el-GR.json +++ b/front/app/translations/el-GR.json @@ -235,11 +235,9 @@ "app.components.InitiativeCards.xInitiatives": "{initiativesCount, plural, one {# πρόταση} other {# προτάσεις}}", "app.components.InitiativeForm.bannerUploadLabel": "Προσθέστε ένα μπάνερ", "app.components.InitiativeForm.bannerUploadLabelSubtext": "Κάντε τη σελίδα σας οπτικά πιο ελκυστική. Αυτή η εικόνα θα εμφανίζεται στην κορυφή της σελίδας σας.", - "app.components.InitiativeForm.cosponsorSectionTitle": "Χρειάζονται συνυποστηρικτές για την αναθεώρηση", "app.components.InitiativeForm.cosponsorSubtextBeforeInput": "Απαιτείται να έχετε τουλάχιστον {noOfCosponsorsText} στην πρότασή σας. Προσκαλέστε τους συνυποστηρικτές μέσω του παρακάτω πεδίου. Ο/οι προσκεκλημένος/οι συνυποστηρικτής/ές θα λάβει/ουν ένα μήνυμα ηλεκτρονικού ταχυδρομείου.", "app.components.InitiativeForm.cosponsorSubtextBeforeInputNote": "Οι συνυποστηρικτές σας χρειάζονται λογαριασμό σε αυτόν τον ιστότοπο για να εμφανιστούν σε αυτόν τον κατάλογο.", "app.components.InitiativeForm.cosponsorsEmptyError": "Προσθέστε τον απαιτούμενο αριθμό συνυποστηρικτών", - "app.components.InitiativeForm.cosponsorsLabel": "Συνυπογράφοντες", "app.components.InitiativeForm.cosponsorsMaxError": "Μπορείτε να προσθέσετε μόνο {maxNumberOfCosponsors} συνυποστηρικτές", "app.components.InitiativeForm.cosponsorsPlaceholder": "Αρχίστε να πληκτρολογείτε ένα όνομα για αναζήτηση", "app.components.InitiativeForm.descriptionBodyLengthError": "Η περιγραφή πρέπει να είναι τουλάχιστον 30 χαρακτήρες", diff --git a/front/app/translations/en-CA.json b/front/app/translations/en-CA.json index d1a819b030b2..cfecac60586e 100644 --- a/front/app/translations/en-CA.json +++ b/front/app/translations/en-CA.json @@ -235,11 +235,9 @@ "app.components.InitiativeCards.xInitiatives": "{initiativesCount, plural, one {# proposal} other {# proposals}}", "app.components.InitiativeForm.bannerUploadLabel": "Add a banner", "app.components.InitiativeForm.bannerUploadLabelSubtext": "Make your page visually more appealing. This image will be shown on top of your page.", - "app.components.InitiativeForm.cosponsorSectionTitle": "Cosponsors needed for review", "app.components.InitiativeForm.cosponsorSubtextBeforeInput": "It's required that you have at least {noOfCosponsorsText} on your proposal. Invite cosponsors through the field below. The invited cosponsor(s) will receive an email.", "app.components.InitiativeForm.cosponsorSubtextBeforeInputNote": "Your cosponsors need an account on this website before they'll appear in this list.", "app.components.InitiativeForm.cosponsorsEmptyError": "Please add the required number of cosponsors", - "app.components.InitiativeForm.cosponsorsLabel": "Cosponsors", "app.components.InitiativeForm.cosponsorsMaxError": "You can only add {maxNumberOfCosponsors} cosponsors", "app.components.InitiativeForm.cosponsorsPlaceholder": "Start typing a name to search", "app.components.InitiativeForm.descriptionBodyLengthError": "The description must be at least 30 characters long", diff --git a/front/app/translations/en-GB.json b/front/app/translations/en-GB.json index c824a0a23f9d..c164c5cd2dcf 100644 --- a/front/app/translations/en-GB.json +++ b/front/app/translations/en-GB.json @@ -235,11 +235,9 @@ "app.components.InitiativeCards.xInitiatives": "{initiativesCount, plural, one {# post} other {# posts}}", "app.components.InitiativeForm.bannerUploadLabel": "Add a banner", "app.components.InitiativeForm.bannerUploadLabelSubtext": "Make your page visually more appealing. This image will be shown on top of your page.", - "app.components.InitiativeForm.cosponsorSectionTitle": "Cosponsors needed for review", "app.components.InitiativeForm.cosponsorSubtextBeforeInput": "It's required that you have at least {noOfCosponsorsText} on your proposal. Invite cosponsors through the field below. The invited cosponsor(s) will receive an email.", "app.components.InitiativeForm.cosponsorSubtextBeforeInputNote": "Your cosponsors need an account on this website before they'll appear in this list.", "app.components.InitiativeForm.cosponsorsEmptyError": "Please add the required number of cosponsors", - "app.components.InitiativeForm.cosponsorsLabel": "Cosponsors", "app.components.InitiativeForm.cosponsorsMaxError": "You can only add {maxNumberOfCosponsors} cosponsors", "app.components.InitiativeForm.cosponsorsPlaceholder": "Start typing a name to search", "app.components.InitiativeForm.descriptionBodyLengthError": "The description must be at least 30 characters long", diff --git a/front/app/translations/en-IE.json b/front/app/translations/en-IE.json index ed622e67cd2e..2f3b494ac14f 100644 --- a/front/app/translations/en-IE.json +++ b/front/app/translations/en-IE.json @@ -235,11 +235,9 @@ "app.components.InitiativeCards.xInitiatives": "{initiativesCount, plural, one {# proposal} other {# proposals}}", "app.components.InitiativeForm.bannerUploadLabel": "Add a banner", "app.components.InitiativeForm.bannerUploadLabelSubtext": "Make your page visually more appealing. This image will be shown on top of your page.", - "app.components.InitiativeForm.cosponsorSectionTitle": "Cosponsors needed for review", "app.components.InitiativeForm.cosponsorSubtextBeforeInput": "It's required that you have at least {noOfCosponsorsText} on your proposal. Invite cosponsors through the field below. The invited cosponsor(s) will receive an email.", "app.components.InitiativeForm.cosponsorSubtextBeforeInputNote": "Your cosponsors need an account on this website before they'll appear in this list.", "app.components.InitiativeForm.cosponsorsEmptyError": "Please add the required number of cosponsors", - "app.components.InitiativeForm.cosponsorsLabel": "Cosponsors", "app.components.InitiativeForm.cosponsorsMaxError": "You can only add {maxNumberOfCosponsors} cosponsors", "app.components.InitiativeForm.cosponsorsPlaceholder": "Start typing a name to search", "app.components.InitiativeForm.descriptionBodyLengthError": "The description must be at least 30 characters long", diff --git a/front/app/translations/en.json b/front/app/translations/en.json index 19318dc38779..9d61ce08b1b3 100644 --- a/front/app/translations/en.json +++ b/front/app/translations/en.json @@ -235,11 +235,11 @@ "app.components.InitiativeCards.xInitiatives": "{initiativesCount, plural, one {# proposal} other {# proposals}}", "app.components.InitiativeForm.bannerUploadLabel": "Add a banner", "app.components.InitiativeForm.bannerUploadLabelSubtext": "Make your page visually more appealing. This image will be shown on top of your page.", - "app.components.InitiativeForm.cosponsorSectionTitle": "Cosponsors needed for review", + "app.components.InitiativeForm.co-sponsorSectionTitle": "Co-sponsors needed for review", + "app.components.InitiativeForm.co-sponsorsLabel": "Co-sponsors", "app.components.InitiativeForm.cosponsorSubtextBeforeInput": "It's required that you have at least {noOfCosponsorsText} on your proposal. Invite cosponsors through the field below. The invited cosponsor(s) will receive an email.", "app.components.InitiativeForm.cosponsorSubtextBeforeInputNote": "Your cosponsors need an account on this website before they'll appear in this list.", "app.components.InitiativeForm.cosponsorsEmptyError": "Please add the required number of cosponsors", - "app.components.InitiativeForm.cosponsorsLabel": "Cosponsors", "app.components.InitiativeForm.cosponsorsMaxError": "You can only add {maxNumberOfCosponsors} cosponsors", "app.components.InitiativeForm.cosponsorsPlaceholder": "Start typing a name to search", "app.components.InitiativeForm.descriptionBodyLengthError": "The description must be at least 30 characters long", @@ -1318,11 +1318,11 @@ "app.containers.IdeasNewPage.projectMetaTitle1": "Add new project to project | {orgName}", "app.containers.IdeasNewPage.questionMetaTitle1": "Add new question to project | {orgName}", "app.containers.IdeasNewPage.surveyNewMetaTitle1": "Add survey response to project | {orgName}", - "app.containers.IdeasShow.Cosponsorship.cosponsorAcceptInvitation": "Accept invitation", - "app.containers.IdeasShow.Cosponsorship.cosponsorDescription": "You have been invited become a cosponsor.", - "app.containers.IdeasShow.Cosponsorship.cosponsorInvitation": "Cosponsorship invitation", + "app.containers.IdeasShow.Cosponsorship.co-sponsorAcceptInvitation": "Accept invitation", + "app.containers.IdeasShow.Cosponsorship.co-sponsorDescription": "You have been invited become a co-sponsor.", + "app.containers.IdeasShow.Cosponsorship.co-sponsorInvitation": "Co-sponsorship invitation", + "app.containers.IdeasShow.Cosponsorship.co-sponsors": "Co-sponsors", "app.containers.IdeasShow.Cosponsorship.cosponsorInvitationAccepted": "Invitation accepted", - "app.containers.IdeasShow.Cosponsorship.cosponsors": "Cosponsors", "app.containers.IdeasShow.Cosponsorship.pending": "pending", "app.containers.IdeasShow.MetaInformation.attachments": "Attachments", "app.containers.IdeasShow.MetaInformation.byUserOnDate": "{userName} on {date}", diff --git a/front/app/translations/es-CL.json b/front/app/translations/es-CL.json index cca7a53e9eea..82035cf31a15 100644 --- a/front/app/translations/es-CL.json +++ b/front/app/translations/es-CL.json @@ -235,11 +235,9 @@ "app.components.InitiativeCards.xInitiatives": "{initiativesCount, plural, no {# propuestas} one {# propuesta} other {# propuestas}}", "app.components.InitiativeForm.bannerUploadLabel": "Añadir un banner", "app.components.InitiativeForm.bannerUploadLabelSubtext": "Haz que tu página sea visualmente más atractiva. Esta imagen se mostrará en la parte superior de tu página.", - "app.components.InitiativeForm.cosponsorSectionTitle": "Copatrocinadores necesarios para su revisión", "app.components.InitiativeForm.cosponsorSubtextBeforeInput": "Es obligatorio que tengas al menos {noOfCosponsorsText} en tu propuesta. Invita a los copatrocinadores a través del siguiente campo. Los copatrocinadores invitados recibirán un correo electrónico.", "app.components.InitiativeForm.cosponsorSubtextBeforeInputNote": "Tus copatrocinadores necesitan una cuenta en este sitio web antes de que aparezcan en esta lista.", "app.components.InitiativeForm.cosponsorsEmptyError": "Por favor, añade el número necesario de copatrocinadores", - "app.components.InitiativeForm.cosponsorsLabel": "Copatrocinadores", "app.components.InitiativeForm.cosponsorsMaxError": "Sólo puedes añadir copatrocinadores a {maxNumberOfCosponsors}", "app.components.InitiativeForm.cosponsorsPlaceholder": "Empezar a escribir un nombre para buscar", "app.components.InitiativeForm.descriptionBodyLengthError": "La descripción debe tener al menos 30 caracteres", diff --git a/front/app/translations/es-ES.json b/front/app/translations/es-ES.json index 37a48b40cd32..9dea47781fd0 100644 --- a/front/app/translations/es-ES.json +++ b/front/app/translations/es-ES.json @@ -235,11 +235,9 @@ "app.components.InitiativeCards.xInitiatives": "{initiativesCount, plural, no {# propuestas} one {# propuesta} other {# propuestas}}", "app.components.InitiativeForm.bannerUploadLabel": "Añadir un banner", "app.components.InitiativeForm.bannerUploadLabelSubtext": "Haz que tu página sea visualmente más atractiva. Esta imagen se mostrará en la parte superior de tu página.", - "app.components.InitiativeForm.cosponsorSectionTitle": "Se necesitan copatrocinadores para la revisión", "app.components.InitiativeForm.cosponsorSubtextBeforeInput": "Es necesario que tengas al menos {noOfCosponsorsText} en tu propuesta. Invita a copatrocinadores a través del campo de abajo. Los copatrocinadores invitados recibirán un correo electrónico.", "app.components.InitiativeForm.cosponsorSubtextBeforeInputNote": "Tus copatrocinadores necesitan una cuenta en este sitio web para aparecer en esta lista.", "app.components.InitiativeForm.cosponsorsEmptyError": "Por favor, añade el número necesario de copatrocinadores", - "app.components.InitiativeForm.cosponsorsLabel": "Copatrocinadores", "app.components.InitiativeForm.cosponsorsMaxError": "Sólo puedes añadir copatrocinadores a {maxNumberOfCosponsors}", "app.components.InitiativeForm.cosponsorsPlaceholder": "Empieza a escribir un nombre para buscar", "app.components.InitiativeForm.descriptionBodyLengthError": "La descripción debe tener al menos 30 caracteres", diff --git a/front/app/translations/fi-FI.json b/front/app/translations/fi-FI.json index 704954df5d26..efccfae51883 100644 --- a/front/app/translations/fi-FI.json +++ b/front/app/translations/fi-FI.json @@ -235,11 +235,9 @@ "app.components.InitiativeCards.xInitiatives": "{initiativesCount, plural, one {# ehdotus} other {# ehdotus}}", "app.components.InitiativeForm.bannerUploadLabel": "Lisää banneri", "app.components.InitiativeForm.bannerUploadLabelSubtext": "Tee sivustasi visuaalisesti houkuttelevampi. Tämä kuva näytetään sivusi yläosassa.", - "app.components.InitiativeForm.cosponsorSectionTitle": "Katsastukseen tarvitaan tukijoita", "app.components.InitiativeForm.cosponsorSubtextBeforeInput": "Ehdotuksessasi on oltava vähintään {noOfCosponsorsText} . Kutsu sponsoreita alla olevan kentän kautta. Kutsutut sponsorit saavat sähköpostin.", "app.components.InitiativeForm.cosponsorSubtextBeforeInputNote": "Avustajasi tarvitsevat tilin tällä verkkosivustolla ennen kuin he näkyvät tässä luettelossa.", "app.components.InitiativeForm.cosponsorsEmptyError": "Lisää tarvittava määrä tukijoita", - "app.components.InitiativeForm.cosponsorsLabel": "Kannattajat", "app.components.InitiativeForm.cosponsorsMaxError": "Voit lisätä vain {maxNumberOfCosponsors} sponsoreita", "app.components.InitiativeForm.cosponsorsPlaceholder": "Aloita etsittävän nimen kirjoittaminen", "app.components.InitiativeForm.descriptionBodyLengthError": "Kuvauksen tulee olla vähintään 30 merkkiä pitkä", diff --git a/front/app/translations/fr-BE.json b/front/app/translations/fr-BE.json index f15fddfbbf28..3565ca00794d 100644 --- a/front/app/translations/fr-BE.json +++ b/front/app/translations/fr-BE.json @@ -235,11 +235,9 @@ "app.components.InitiativeCards.xInitiatives": "{initiativesCount, plural, no {# propositions} one {# proposition} other {# propositions}}", "app.components.InitiativeForm.bannerUploadLabel": "Ajouter une bannière", "app.components.InitiativeForm.bannerUploadLabelSubtext": "Rendez votre page visuellement plus attrayante. Cette image sera affichée en haut de votre page.", - "app.components.InitiativeForm.cosponsorSectionTitle": "Soutiens requis pour soumettre la proposition", "app.components.InitiativeForm.cosponsorSubtextBeforeInput": "Vous devez obtenir au moins {noOfCosponsorsText} pour votre proposition. Invitez des soutiens en utilisant le champ ci-dessous. Les personnes invitées recevront un e-mail.", "app.components.InitiativeForm.cosponsorSubtextBeforeInputNote": "Vos soutiens doivent disposer d'un compte sur cette plateforme pour apparaître dans cette liste.", "app.components.InitiativeForm.cosponsorsEmptyError": "Veuillez ajouter le nombre requis de soutiens", - "app.components.InitiativeForm.cosponsorsLabel": "Soutiens", "app.components.InitiativeForm.cosponsorsMaxError": "Vous ne pouvez solliciter que jusqu'à {maxNumberOfCosponsors} soutiens", "app.components.InitiativeForm.cosponsorsPlaceholder": "Commencez à taper un nom pour lancer une recherche", "app.components.InitiativeForm.descriptionBodyLengthError": "La description doit comporter au moins 30 caractères", diff --git a/front/app/translations/fr-FR.json b/front/app/translations/fr-FR.json index 6ab3375e8017..ad68f2780cb2 100644 --- a/front/app/translations/fr-FR.json +++ b/front/app/translations/fr-FR.json @@ -235,11 +235,9 @@ "app.components.InitiativeCards.xInitiatives": "{initiativesCount, plural, no {# propositions} one {# proposition} other {# propositions}}", "app.components.InitiativeForm.bannerUploadLabel": "Ajouter une bannière", "app.components.InitiativeForm.bannerUploadLabelSubtext": "Rendez votre page visuellement plus attrayante. Cette image sera affichée en haut de votre page.", - "app.components.InitiativeForm.cosponsorSectionTitle": "Soutiens requis pour soumettre la proposition", "app.components.InitiativeForm.cosponsorSubtextBeforeInput": "Vous devez obtenir au moins {noOfCosponsorsText} pour votre proposition. Invitez des soutiens en utilisant le champ ci-dessous. Les personnes invitées recevront un e-mail.", "app.components.InitiativeForm.cosponsorSubtextBeforeInputNote": "Vos soutiens doivent disposer d'un compte sur cette plateforme pour apparaître dans cette liste.", "app.components.InitiativeForm.cosponsorsEmptyError": "Veuillez ajouter le nombre requis de soutiens", - "app.components.InitiativeForm.cosponsorsLabel": "Soutiens", "app.components.InitiativeForm.cosponsorsMaxError": "Vous ne pouvez solliciter que jusqu'à {maxNumberOfCosponsors} soutiens", "app.components.InitiativeForm.cosponsorsPlaceholder": "Commencez à taper un nom pour lancer une recherche", "app.components.InitiativeForm.descriptionBodyLengthError": "La description doit comporter au moins 30 caractères", diff --git a/front/app/translations/hr-HR.json b/front/app/translations/hr-HR.json index afb9814b0fc9..4ef744ffef6a 100644 --- a/front/app/translations/hr-HR.json +++ b/front/app/translations/hr-HR.json @@ -235,11 +235,9 @@ "app.components.InitiativeCards.xInitiatives": "{initiativesCount, plural, one {# prijedlog} other {# prijedloga}}", "app.components.InitiativeForm.bannerUploadLabel": "Dodajte natpis", "app.components.InitiativeForm.bannerUploadLabelSubtext": "Učinite svoju stranicu atraktivnijom. Ova slika će se prikazivati na njenom vrhu.", - "app.components.InitiativeForm.cosponsorSectionTitle": "Potrebni kosponzori za pregled", "app.components.InitiativeForm.cosponsorSubtextBeforeInput": "Potrebno je da imate najmanje {noOfCosponsorsText} na svom prijedlogu. Pozovite kosponzore putem donjeg polja. Pozvani susponzori primit će e-poruku.", "app.components.InitiativeForm.cosponsorSubtextBeforeInputNote": "Vaši kosponzori trebaju račun na ovoj web stranici prije nego što se pojave na ovom popisu.", "app.components.InitiativeForm.cosponsorsEmptyError": "Molimo dodajte potreban broj kosponzora", - "app.components.InitiativeForm.cosponsorsLabel": "Kosponzori", "app.components.InitiativeForm.cosponsorsMaxError": "Možete dodati samo {maxNumberOfCosponsors} kosponzora", "app.components.InitiativeForm.cosponsorsPlaceholder": "Počnite upisivati ime za pretraživanje", "app.components.InitiativeForm.descriptionBodyLengthError": "Opis mora sadržavati barem 30 znakova", diff --git a/front/app/translations/it-IT.json b/front/app/translations/it-IT.json index 995fc22209e8..1e9eb577ae4c 100644 --- a/front/app/translations/it-IT.json +++ b/front/app/translations/it-IT.json @@ -235,11 +235,9 @@ "app.components.InitiativeCards.xInitiatives": "{initiativesCount, plural, one {# proposta} other {# proposte}}", "app.components.InitiativeForm.bannerUploadLabel": "Aggiungere un banner", "app.components.InitiativeForm.bannerUploadLabelSubtext": "Rendi la tua pagina visivamente più attraente. Questa immagine sarà mostrata in cima alla tua pagina.", - "app.components.InitiativeForm.cosponsorSectionTitle": "Sono necessari dei cosponsor per la revisione", "app.components.InitiativeForm.cosponsorSubtextBeforeInput": "È necessario che almeno {noOfCosponsorsText} sia presente nella tua proposta. Invita i cosponsor attraverso il campo sottostante. I cosponsor invitati riceveranno un'e-mail.", "app.components.InitiativeForm.cosponsorSubtextBeforeInputNote": "I tuoi cosponsor devono avere un account su questo sito web per poter apparire in questo elenco.", "app.components.InitiativeForm.cosponsorsEmptyError": "Aggiungi il numero richiesto di cosponsor", - "app.components.InitiativeForm.cosponsorsLabel": "Cosponsor", "app.components.InitiativeForm.cosponsorsMaxError": "Puoi aggiungere solo {maxNumberOfCosponsors} cosponsor", "app.components.InitiativeForm.cosponsorsPlaceholder": "Inizia a digitare un nome da cercare", "app.components.InitiativeForm.descriptionBodyLengthError": "La descrizione deve essere lunga almeno 30 caratteri", diff --git a/front/app/translations/kl-GL.json b/front/app/translations/kl-GL.json index 8d99f68ee48a..08b3c8a4defc 100644 --- a/front/app/translations/kl-GL.json +++ b/front/app/translations/kl-GL.json @@ -186,10 +186,8 @@ "app.components.InitiativeCards.xInitiatives": "{initiativesCount, plural, one {# innuttaasunit siunnersuut} other {# innuttaasunit siunnersuut}}", "app.components.InitiativeForm.bannerUploadLabel": "Bannerimik ilanngussigit", "app.components.InitiativeForm.bannerUploadLabelSubtext": "Quppernerit takuneqarsinnaasumik takujuminarnerulersiguk Una asseq quppernerni qullerpaami nuisavoq.", - "app.components.InitiativeForm.cosponsorSectionTitle": "Cosponsors needed for review", "app.components.InitiativeForm.cosponsorSubtextBeforeInput": "It's required that you have at least {noOfCosponsorsText} on your proposal. Invite cosponsors through the field below. The invited cosponsor(s) will receive an email.", "app.components.InitiativeForm.cosponsorSubtextBeforeInputNote": "Your cosponsors need an account on this website before they'll appear in this list.", - "app.components.InitiativeForm.cosponsorsLabel": "Cosponsors", "app.components.InitiativeForm.cosponsorsPlaceholder": "Start typing a name to search", "app.components.InitiativeForm.descriptionBodyLengthError": "Isumassarsiamik allaaserinninneq minnerpaamik naqinnernik 30-nik imaqassaaq", "app.components.InitiativeForm.descriptionEmptyError": "Allaatiginnilaarit ", diff --git a/front/app/translations/lb-LU.json b/front/app/translations/lb-LU.json index 3f60bd306bc7..c4ad9e013388 100644 --- a/front/app/translations/lb-LU.json +++ b/front/app/translations/lb-LU.json @@ -235,11 +235,9 @@ "app.components.InitiativeCards.xInitiatives": "{initiativesCount, plural, one {# Virschlag} other {# Virschléi}}", "app.components.InitiativeForm.bannerUploadLabel": "E Banner bäifügen", "app.components.InitiativeForm.bannerUploadLabelSubtext": "Gestalt Är Säit optesch méi uspriechend. Dëst Bild gëtt uewen op Ärer Säit gewisen.", - "app.components.InitiativeForm.cosponsorSectionTitle": "Cosponsoren néideg fir Iwwerpréiwung", "app.components.InitiativeForm.cosponsorSubtextBeforeInput": "Et ass erfuerderlech datt Dir op d'mannst {noOfCosponsorsText} op Ärer Propositioun hutt. Invitéiert Cosponsoren duerch d'Feld hei drënner. Den invitéierte Cosponsor (en) kritt eng E-Mail.", "app.components.InitiativeForm.cosponsorSubtextBeforeInputNote": "Är Cosponsoren brauchen e Kont op dëser Websäit ier se an dëser Lëscht erschéngen.", "app.components.InitiativeForm.cosponsorsEmptyError": "Füügt w.e.g. déi erfuerderlech Unzuel u Cosponsoren derbäi", - "app.components.InitiativeForm.cosponsorsLabel": "Cosponsoren", "app.components.InitiativeForm.cosponsorsMaxError": "Dir kënnt nëmmen {maxNumberOfCosponsors} Cosponsoren derbäi", "app.components.InitiativeForm.cosponsorsPlaceholder": "Fänkt un en Numm ze schreiwen fir ze sichen", "app.components.InitiativeForm.descriptionBodyLengthError": "D’Beschreiwung muss mindestens 30 Zeeche hunn", diff --git a/front/app/translations/lv-LV.json b/front/app/translations/lv-LV.json index e41acf2a085c..5761ec369629 100644 --- a/front/app/translations/lv-LV.json +++ b/front/app/translations/lv-LV.json @@ -235,11 +235,9 @@ "app.components.InitiativeCards.xInitiatives": "{initiativesCount, plural, one {# priekšlikums} other {# priekšlikumi}}", "app.components.InitiativeForm.bannerUploadLabel": "Pievienot reklāmkarogu", "app.components.InitiativeForm.bannerUploadLabelSubtext": "Padariet lapu vizuāli pievilcīgāku. Šis attēls tiks parādīts jūsu lapas augšpusē.", - "app.components.InitiativeForm.cosponsorSectionTitle": "Pārskatīšanai vajadzīgi līdzpriekšsēdētāji", "app.components.InitiativeForm.cosponsorSubtextBeforeInput": "Jūsu priekšlikumam ir jābūt vismaz {noOfCosponsorsText} . Uzaiciniet līdzpiedāvātājus, izmantojot zemāk redzamo lauku. Uzaicinātais(-ie) līdzsadarbinieks(-i) saņems e-pasta vēstuli.", "app.components.InitiativeForm.cosponsorSubtextBeforeInputNote": "Lai jūsu līdzfinansētāji parādītos šajā sarakstā, viņiem ir nepieciešams konts šajā tīmekļa vietnē.", "app.components.InitiativeForm.cosponsorsEmptyError": "Lūdzu, pievienojiet vajadzīgo līdzpriekšsēdētāju skaitu.", - "app.components.InitiativeForm.cosponsorsLabel": "Atbalstītāji", "app.components.InitiativeForm.cosponsorsMaxError": "Jūs varat pievienot tikai {maxNumberOfCosponsors} līdzpriekšsēdētājus.", "app.components.InitiativeForm.cosponsorsPlaceholder": "Sāciet ierakstīt nosaukumu, lai veiktu meklēšanu", "app.components.InitiativeForm.descriptionBodyLengthError": "Aprakstam jābūt vismaz 30 rakstu zīmju garam", diff --git a/front/app/translations/nb-NO.json b/front/app/translations/nb-NO.json index fd4c8b446664..c606de8f0435 100644 --- a/front/app/translations/nb-NO.json +++ b/front/app/translations/nb-NO.json @@ -235,11 +235,9 @@ "app.components.InitiativeCards.xInitiatives": "{initiativesCount, plural, one {# forslag} other {# forslag}}", "app.components.InitiativeForm.bannerUploadLabel": "Legg til banner", "app.components.InitiativeForm.bannerUploadLabelSubtext": "Gjør siden din mer visuell. Bildet vil vises øverst på siden din.", - "app.components.InitiativeForm.cosponsorSectionTitle": "Medsponsorer trengs for gjennomgang", "app.components.InitiativeForm.cosponsorSubtextBeforeInput": "Det kreves at du har minst {noOfCosponsorsText} på forslaget. Inviter medsponsorer gjennom feltet nedenfor. Den/de inviterte medsponsoren(e) vil motta en e-post.", "app.components.InitiativeForm.cosponsorSubtextBeforeInputNote": "Dine medsponsorer trenger en konto på denne nettsiden før de vises i denne listen.", "app.components.InitiativeForm.cosponsorsEmptyError": "Vennligst legg til det nødvendige antallet medsponsorer", - "app.components.InitiativeForm.cosponsorsLabel": "Medsponsorer", "app.components.InitiativeForm.cosponsorsMaxError": "Du kan bare legge til {maxNumberOfCosponsors} medsponsorer", "app.components.InitiativeForm.cosponsorsPlaceholder": "Begynn å skrive et navn for å søke", "app.components.InitiativeForm.descriptionBodyLengthError": "Beskrivelse må være minst 30 tegn", diff --git a/front/app/translations/nl-BE.json b/front/app/translations/nl-BE.json index 748b196ddc92..5760e558b40b 100644 --- a/front/app/translations/nl-BE.json +++ b/front/app/translations/nl-BE.json @@ -235,11 +235,9 @@ "app.components.InitiativeCards.xInitiatives": "{initiativesCount, plural, one {# voorstel} other {# voorstellen}}", "app.components.InitiativeForm.bannerUploadLabel": "Voeg een coverafbeelding toe", "app.components.InitiativeForm.bannerUploadLabelSubtext": "Maak je pagina visueel aantrekkelijker. Deze afbeelding wordt bovenaan je pagina weergegeven.", - "app.components.InitiativeForm.cosponsorSectionTitle": "Ondersteuners nodig voor beoordeling", "app.components.InitiativeForm.cosponsorSubtextBeforeInput": "Het is vereist dat je minimaal {noOfCosponsorsText} voor je voorstel hebt. Nodig ondersteuners uit via het onderstaande veld. De uitgenodigde ondersteuner(s) ontvangen een e-mail.", "app.components.InitiativeForm.cosponsorSubtextBeforeInputNote": "Je ondersteuners moeten een account hebben op deze website voordat ze in deze lijst verschijnen.", "app.components.InitiativeForm.cosponsorsEmptyError": "Voeg het vereiste aantal ondersteuners toe", - "app.components.InitiativeForm.cosponsorsLabel": "Ondersteuners", "app.components.InitiativeForm.cosponsorsMaxError": "Je kunt alleen {maxNumberOfCosponsors} ondersteuners toevoegen", "app.components.InitiativeForm.cosponsorsPlaceholder": "Begin met het typen van een naam om te zoeken", "app.components.InitiativeForm.descriptionBodyLengthError": "De beschrijving moet minstens 30 tekens lang zijn", diff --git a/front/app/translations/nl-NL.json b/front/app/translations/nl-NL.json index 3e11c6ec32e2..9978af168a66 100644 --- a/front/app/translations/nl-NL.json +++ b/front/app/translations/nl-NL.json @@ -235,11 +235,9 @@ "app.components.InitiativeCards.xInitiatives": "{initiativesCount, plural, one {# voorstel} other {# voorstellen}}", "app.components.InitiativeForm.bannerUploadLabel": "Voeg een coverafbeelding toe", "app.components.InitiativeForm.bannerUploadLabelSubtext": "Maak je pagina visueel aantrekkelijker. Deze afbeelding wordt bovenaan je pagina weergegeven.", - "app.components.InitiativeForm.cosponsorSectionTitle": "Ondersteuners nodig voor beoordeling", "app.components.InitiativeForm.cosponsorSubtextBeforeInput": "Het is vereist dat je minimaal {noOfCosponsorsText} voor je voorstel hebt. Nodig ondersteuners uit via het onderstaande veld. De uitgenodigde ondersteuner(s) ontvangen een e-mail.", "app.components.InitiativeForm.cosponsorSubtextBeforeInputNote": "Je ondersteuners moeten een account hebben op deze website voordat ze in deze lijst verschijnen.", "app.components.InitiativeForm.cosponsorsEmptyError": "Voeg het vereiste aantal ondersteuners toe", - "app.components.InitiativeForm.cosponsorsLabel": "Ondersteuners", "app.components.InitiativeForm.cosponsorsMaxError": "Je kunt alleen {maxNumberOfCosponsors} ondersteuners toevoegen", "app.components.InitiativeForm.cosponsorsPlaceholder": "Begin met het typen van een naam om te zoeken", "app.components.InitiativeForm.descriptionBodyLengthError": "De beschrijving moet minstens 30 tekens lang zijn", diff --git a/front/app/translations/pl-PL.json b/front/app/translations/pl-PL.json index e42f6c30af24..491efdae0107 100644 --- a/front/app/translations/pl-PL.json +++ b/front/app/translations/pl-PL.json @@ -235,11 +235,9 @@ "app.components.InitiativeCards.xInitiatives": "{initiativesCount, plural, one {# propozycja} few {# propozycje} many {# propozycji} other {# propozycje}}", "app.components.InitiativeForm.bannerUploadLabel": "Dodaj baner", "app.components.InitiativeForm.bannerUploadLabelSubtext": "Uczyń swoją stronę bardziej atrakcyjną wizualnie. Ten obrazek zostanie wyświetlony na górze strony.", - "app.components.InitiativeForm.cosponsorSectionTitle": "Sponsorzy potrzebni do przeglądu", "app.components.InitiativeForm.cosponsorSubtextBeforeInput": "Wymagane jest, aby Twój wniosek zawierał co najmniej {noOfCosponsorsText} . Zaproś współsponsorów za pomocą poniższego pola. Zaproszeni współsponsorzy otrzymają wiadomość e-mail.", "app.components.InitiativeForm.cosponsorSubtextBeforeInputNote": "Twoi współwnioskodawcy muszą mieć konto na tej stronie, zanim pojawią się na tej liście.", "app.components.InitiativeForm.cosponsorsEmptyError": "Dodaj wymaganą liczbę współwnioskodawców", - "app.components.InitiativeForm.cosponsorsLabel": "Współsponsorzy", "app.components.InitiativeForm.cosponsorsMaxError": "Możesz dodać tylko {maxNumberOfCosponsors} współwnioskodawców", "app.components.InitiativeForm.cosponsorsPlaceholder": "Zacznij wpisywać nazwę do wyszukania", "app.components.InitiativeForm.descriptionBodyLengthError": "Opis inicjatywy musi składać się z co najmniej 30 znaków", diff --git a/front/app/translations/pt-BR.json b/front/app/translations/pt-BR.json index b2dede4a1a90..5cdcab93011a 100644 --- a/front/app/translations/pt-BR.json +++ b/front/app/translations/pt-BR.json @@ -235,11 +235,9 @@ "app.components.InitiativeCards.xInitiatives": "{initiativesCount, plural, one {# proposta} other {# propostas}}", "app.components.InitiativeForm.bannerUploadLabel": "Adicionar um banner", "app.components.InitiativeForm.bannerUploadLabelSubtext": "Torne sua página visualmente mais atraente. Esta imagem será mostrada na parte superior da sua página.", - "app.components.InitiativeForm.cosponsorSectionTitle": "Necessidade de co-patrocinadores para a revisão", "app.components.InitiativeForm.cosponsorSubtextBeforeInput": "É necessário que tenha pelo menos {noOfCosponsorsText} na sua proposta. Convide os co-patrocinadores através do campo abaixo. O(s) copatrocinador(es) convidado(s) receberá(ão) uma mensagem de e-mail.", "app.components.InitiativeForm.cosponsorSubtextBeforeInputNote": "Seus co-patrocinadores precisam de uma conta neste site antes de aparecerem nesta lista.", "app.components.InitiativeForm.cosponsorsEmptyError": "Acrescentar o número necessário de co-patrocinadores", - "app.components.InitiativeForm.cosponsorsLabel": "Co-patrocinadores", "app.components.InitiativeForm.cosponsorsMaxError": "Só é possível adicionar {maxNumberOfCosponsors} co-patrocinadores", "app.components.InitiativeForm.cosponsorsPlaceholder": "Comece a digitar um nome para pesquisar", "app.components.InitiativeForm.descriptionBodyLengthError": "A descrição deve ter pelo menos 30 caracteres", diff --git a/front/app/translations/sr-Latn.json b/front/app/translations/sr-Latn.json index e322fdd7864a..3b2d214793c8 100644 --- a/front/app/translations/sr-Latn.json +++ b/front/app/translations/sr-Latn.json @@ -235,11 +235,9 @@ "app.components.InitiativeCards.xInitiatives": "{initiativesCount, plural, one {# predlog} other {# predloga}}", "app.components.InitiativeForm.bannerUploadLabel": "Dodajte baner", "app.components.InitiativeForm.bannerUploadLabelSubtext": "Učinite vašu stranicu atraktivnijom. Ova slika će se prikazivati na njenom vrhu.", - "app.components.InitiativeForm.cosponsorSectionTitle": "Cosponsors needed for review", "app.components.InitiativeForm.cosponsorSubtextBeforeInput": "It's required that you have at least {noOfCosponsorsText} on your proposal. Invite cosponsors through the field below. The invited cosponsor(s) will receive an email.", "app.components.InitiativeForm.cosponsorSubtextBeforeInputNote": "Your cosponsors need an account on this website before they'll appear in this list.", "app.components.InitiativeForm.cosponsorsEmptyError": "Please add the required number of cosponsors", - "app.components.InitiativeForm.cosponsorsLabel": "Cosponsors", "app.components.InitiativeForm.cosponsorsMaxError": "You can only add {maxNumberOfCosponsors} cosponsors", "app.components.InitiativeForm.cosponsorsPlaceholder": "Start typing a name to search", "app.components.InitiativeForm.descriptionBodyLengthError": "Opis mora sadržati najmanje 30 karaktera", diff --git a/front/app/translations/sr-SP.json b/front/app/translations/sr-SP.json index 4610e1be87de..6aaee49b42e5 100644 --- a/front/app/translations/sr-SP.json +++ b/front/app/translations/sr-SP.json @@ -235,11 +235,9 @@ "app.components.InitiativeCards.xInitiatives": "{initiativesCount, plural, one {#предлог} other {# предлога}}", "app.components.InitiativeForm.bannerUploadLabel": "Додајте банер", "app.components.InitiativeForm.bannerUploadLabelSubtext": "Учините своју страницу визуелно привлачнијом. Ова слика ће бити приказана на врху ваше странице.", - "app.components.InitiativeForm.cosponsorSectionTitle": "Коспонзори потребни за преглед", "app.components.InitiativeForm.cosponsorSubtextBeforeInput": "Потребно је да имате најмање {noOfCosponsorsText} на свом предлогу. Позовите коспонзоре кроз поље испод. Позвани коспонзор(и) ће добити е-поруку.", "app.components.InitiativeForm.cosponsorSubtextBeforeInputNote": "Вашим коспонзорима је потребан налог на овој веб локацији пре него што се појаве на овој листи.", "app.components.InitiativeForm.cosponsorsEmptyError": "Молимо додајте потребан број коспонзора", - "app.components.InitiativeForm.cosponsorsLabel": "Цоспонсорс", "app.components.InitiativeForm.cosponsorsMaxError": "Можете додати само {maxNumberOfCosponsors} коспонзора", "app.components.InitiativeForm.cosponsorsPlaceholder": "Почните да куцате име за претрагу", "app.components.InitiativeForm.descriptionBodyLengthError": "Опис мора да има најмање 30 знакова", diff --git a/front/app/translations/sv-SE.json b/front/app/translations/sv-SE.json index 899a04aa23db..2d612f4576f0 100644 --- a/front/app/translations/sv-SE.json +++ b/front/app/translations/sv-SE.json @@ -235,11 +235,9 @@ "app.components.InitiativeCards.xInitiatives": "{initiativesCount, plural, one {# förslag} other {# förslag}}", "app.components.InitiativeForm.bannerUploadLabel": "Lägg till en banner", "app.components.InitiativeForm.bannerUploadLabelSubtext": "Gör din sida mer visuellt tilltalande. Den här bilden kommer att visas överst på din sida.", - "app.components.InitiativeForm.cosponsorSectionTitle": "Sponsorer behövs för översyn", "app.components.InitiativeForm.cosponsorSubtextBeforeInput": "Det krävs att du har minst {noOfCosponsorsText} på ditt förslag. Bjud in medförslagsställare via fältet nedan. De inbjudna medförslagsställarna kommer att få ett e-postmeddelande.", "app.components.InitiativeForm.cosponsorSubtextBeforeInputNote": "Dina sponsorer behöver ett konto på denna webbplats innan de visas i denna lista.", "app.components.InitiativeForm.cosponsorsEmptyError": "Lägg till erforderligt antal medförslagsställare", - "app.components.InitiativeForm.cosponsorsLabel": "Medförslagsställare", "app.components.InitiativeForm.cosponsorsMaxError": "Du kan bara lägga till {maxNumberOfCosponsors} medförslagsställare", "app.components.InitiativeForm.cosponsorsPlaceholder": "Börja skriva ett namn för att söka", "app.components.InitiativeForm.descriptionBodyLengthError": "Beskrivningen måste vara minst 30 tecken lång", diff --git a/front/app/translations/tr-TR.json b/front/app/translations/tr-TR.json index d2e00a79a6fb..32ffe42a9900 100644 --- a/front/app/translations/tr-TR.json +++ b/front/app/translations/tr-TR.json @@ -235,11 +235,9 @@ "app.components.InitiativeCards.xInitiatives": "{initiativesCount, plural, one {# öneri} other {# öneri}}", "app.components.InitiativeForm.bannerUploadLabel": "Bant ekleyin", "app.components.InitiativeForm.bannerUploadLabelSubtext": "Sayfanızı görsel olarak daha çekici hale getirin. Bu görsel, sayfanızın en üst kısmında gösterilecek.", - "app.components.InitiativeForm.cosponsorSectionTitle": "İnceleme için sponsorlara ihtiyaç var", "app.components.InitiativeForm.cosponsorSubtextBeforeInput": "Teklifinizde en az {noOfCosponsorsText} adresine sahip olmanız gerekmektedir. Aşağıdaki alan aracılığıyla eş sponsorları davet edin. Davet edilen sponsor(lar) bir e-posta alacaktır.", "app.components.InitiativeForm.cosponsorSubtextBeforeInputNote": "Sponsorlarınızın bu listede görünmeleri için bu web sitesinde bir hesaplarının olması gerekir.", "app.components.InitiativeForm.cosponsorsEmptyError": "Lütfen gerekli sayıda destekçi ekleyin", - "app.components.InitiativeForm.cosponsorsLabel": "Eş Sponsorlar", "app.components.InitiativeForm.cosponsorsMaxError": "Yalnızca {maxNumberOfCosponsors} adresini ekleyebilirsiniz", "app.components.InitiativeForm.cosponsorsPlaceholder": "Aramak için bir isim yazmaya başlayın", "app.components.InitiativeForm.descriptionBodyLengthError": "Açıklama en az 30 karakter uzunluğunda olmalıdır", From 2abe4702535eefb9446f578f391754a1c0577fbd Mon Sep 17 00:00:00 2001 From: Iva Date: Thu, 26 Sep 2024 11:50:42 +0300 Subject: [PATCH 36/43] Fix admin edit idea form for co-sponsors --- .../Form/Components/Controls/CosponsorsControl.tsx | 2 +- .../components/PostPreview/Idea/AdminIdeaEdit.tsx | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/front/app/components/Form/Components/Controls/CosponsorsControl.tsx b/front/app/components/Form/Components/Controls/CosponsorsControl.tsx index 8d432a09c520..919e24207cfa 100644 --- a/front/app/components/Form/Components/Controls/CosponsorsControl.tsx +++ b/front/app/components/Form/Components/Controls/CosponsorsControl.tsx @@ -11,6 +11,7 @@ import { withJsonFormsControlProps } from '@jsonforms/react'; import { WrappedComponentProps } from 'react-intl'; import { MentionItem } from 'react-mentions'; +import { IUser } from 'api/users/types'; import useUsersWithIds from 'api/users/useUsersByIds'; import { FormLabel } from 'components/UI/FormComponents'; @@ -24,7 +25,6 @@ import ErrorDisplay from '../ErrorDisplay'; import { getSubtextElement } from './controlUtils'; import messages from './messages'; -import { IUser } from 'api/users/types'; const CosponsorsControlInner = ({ uischema, diff --git a/front/app/components/admin/PostManager/components/PostPreview/Idea/AdminIdeaEdit.tsx b/front/app/components/admin/PostManager/components/PostPreview/Idea/AdminIdeaEdit.tsx index f7411abae416..d7409500bc82 100644 --- a/front/app/components/admin/PostManager/components/PostPreview/Idea/AdminIdeaEdit.tsx +++ b/front/app/components/admin/PostManager/components/PostPreview/Idea/AdminIdeaEdit.tsx @@ -70,6 +70,14 @@ const AdminIdeaEdit = ({ prop, idea.data.relationships?.topics?.data.map((rel) => rel.id), ]; + } else if ( + prop === 'cosponsor_ids' && + Array.isArray(idea.data.relationships?.cosponsors?.data) + ) { + return [ + prop, + idea.data.relationships?.cosponsors?.data.map((rel) => rel.id), + ]; } else if ( prop === 'idea_images_attributes' && Array.isArray(idea.data.relationships?.idea_images?.data) From be485b33764b39f144e4aa3b42564147063b039e Mon Sep 17 00:00:00 2001 From: Iva Date: Thu, 26 Sep 2024 11:54:56 +0300 Subject: [PATCH 37/43] Add description and fix typo --- back/config/locales/en.yml | 2 +- .../containers/IdeasShow/components/Cosponsorship/messages.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/back/config/locales/en.yml b/back/config/locales/en.yml index cf8634f2dfc7..335aaf3a3556 100644 --- a/back/config/locales/en.yml +++ b/back/config/locales/en.yml @@ -172,7 +172,7 @@ en: description: consponsor_ids: title: Co-sponsors - description: + description: Invite co-sponsors through the field below. The invited co-sponsor(s) will receive an email. location: title: Location description: diff --git a/front/app/containers/IdeasShow/components/Cosponsorship/messages.ts b/front/app/containers/IdeasShow/components/Cosponsorship/messages.ts index ed2c17a93bd4..83a622ea6d72 100644 --- a/front/app/containers/IdeasShow/components/Cosponsorship/messages.ts +++ b/front/app/containers/IdeasShow/components/Cosponsorship/messages.ts @@ -14,8 +14,8 @@ export default defineMessages({ defaultMessage: 'Co-sponsorship invitation', }, cosponsorInvitationDescription: { - id: 'app.containers.IdeasShow.Cosponsorship.co-sponsorDescription', - defaultMessage: 'You have been invited become a co-sponsor.', + id: 'app.containers.IdeasShow.Cosponsorship.cosponsorDescription', + defaultMessage: 'You have been invited to become a co-sponsor.', }, cosponsorInvitationAccepted: { id: 'app.containers.IdeasShow.Cosponsorship.cosponsorInvitationAccepted', From 2b4e61fcbfb23010adf207e9f7b35287aa3b124e Mon Sep 17 00:00:00 2001 From: CircleCI Date: Thu, 26 Sep 2024 08:57:57 +0000 Subject: [PATCH 38/43] Translations updated by CI (extract-intl) --- front/app/translations/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/front/app/translations/en.json b/front/app/translations/en.json index 9d61ce08b1b3..0c054fc3407d 100644 --- a/front/app/translations/en.json +++ b/front/app/translations/en.json @@ -1319,9 +1319,9 @@ "app.containers.IdeasNewPage.questionMetaTitle1": "Add new question to project | {orgName}", "app.containers.IdeasNewPage.surveyNewMetaTitle1": "Add survey response to project | {orgName}", "app.containers.IdeasShow.Cosponsorship.co-sponsorAcceptInvitation": "Accept invitation", - "app.containers.IdeasShow.Cosponsorship.co-sponsorDescription": "You have been invited become a co-sponsor.", "app.containers.IdeasShow.Cosponsorship.co-sponsorInvitation": "Co-sponsorship invitation", "app.containers.IdeasShow.Cosponsorship.co-sponsors": "Co-sponsors", + "app.containers.IdeasShow.Cosponsorship.cosponsorDescription": "You have been invited to become a co-sponsor.", "app.containers.IdeasShow.Cosponsorship.cosponsorInvitationAccepted": "Invitation accepted", "app.containers.IdeasShow.Cosponsorship.pending": "pending", "app.containers.IdeasShow.MetaInformation.attachments": "Attachments", From c490ea1db6885307a2965783f37b2abcef1b53c7 Mon Sep 17 00:00:00 2001 From: Iva Date: Fri, 27 Sep 2024 17:11:19 +0300 Subject: [PATCH 39/43] Fix scope --- back/app/policies/cosponsorship_policy.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/back/app/policies/cosponsorship_policy.rb b/back/app/policies/cosponsorship_policy.rb index f5f007e637f8..5f5297ee710a 100644 --- a/back/app/policies/cosponsorship_policy.rb +++ b/back/app/policies/cosponsorship_policy.rb @@ -10,7 +10,7 @@ def initialize(user, scope) end def resolve - scope.all + scope.where(post_id: Pundit.policy_scope(user, Idea)) end end From 916ed4f128b8944bce32a612fee5cf068664572a Mon Sep 17 00:00:00 2001 From: Iva Date: Fri, 27 Sep 2024 17:15:54 +0300 Subject: [PATCH 40/43] Rename endpoint --- back/app/controllers/web_api/v1/cosponsorships_controller.rb | 2 +- back/app/policies/cosponsorship_policy.rb | 2 +- back/config/routes.rb | 2 +- back/spec/acceptance/cosponsorships_spec.rb | 4 ++-- .../cosponsorship/useAcceptCosponsorshipInvitation.test.ts | 2 +- .../app/api/cosponsorship/useAcceptCosponsorshipInvitation.ts | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/back/app/controllers/web_api/v1/cosponsorships_controller.rb b/back/app/controllers/web_api/v1/cosponsorships_controller.rb index 41a09308062d..6820e87384d9 100644 --- a/back/app/controllers/web_api/v1/cosponsorships_controller.rb +++ b/back/app/controllers/web_api/v1/cosponsorships_controller.rb @@ -16,7 +16,7 @@ def index render json: linked_json(paginated_cosponsorships, WebApi::V1::CosponsorshipSerializer, params: jsonapi_serializer_params) end - def accept_cosponsorship + def accept if @cosponsorship.status == 'pending' @cosponsorship.update(status: 'accepted') # SideFxAcceptedCosponsorshipService.new.after_accept(@cosponsorship, current_user) diff --git a/back/app/policies/cosponsorship_policy.rb b/back/app/policies/cosponsorship_policy.rb index 5f5297ee710a..f38b90f399dd 100644 --- a/back/app/policies/cosponsorship_policy.rb +++ b/back/app/policies/cosponsorship_policy.rb @@ -14,7 +14,7 @@ def resolve end end - def accept_cosponsorship? + def accept? user.id == record.user_id end end diff --git a/back/config/routes.rb b/back/config/routes.rb index fcbd2239b193..f3fc447bff32 100644 --- a/back/config/routes.rb +++ b/back/config/routes.rb @@ -60,7 +60,7 @@ resources :images, defaults: { container_type: 'Idea' } resources :files, defaults: { container_type: 'Idea' } resources :cosponsorships, defaults: { container_type: 'Idea' } do - patch 'accept_cosponsorship', on: :member + patch 'accept', on: :member end get :as_xlsx, on: :collection, action: 'index_xlsx' diff --git a/back/spec/acceptance/cosponsorships_spec.rb b/back/spec/acceptance/cosponsorships_spec.rb index 3189dcc16a78..ed1107e57f85 100644 --- a/back/spec/acceptance/cosponsorships_spec.rb +++ b/back/spec/acceptance/cosponsorships_spec.rb @@ -34,7 +34,7 @@ end context 'when the user is the invited user' do - patch 'web_api/v1/ideas/:idea_id/cosponsorships/:cosponsorship_id/accept_cosponsorship' do + patch 'web_api/v1/ideas/:idea_id/cosponsorships/:cosponsorship_id/accept' do before do header 'Authorization', authorization_header(@user) end @@ -47,7 +47,7 @@ end context 'when the user is not the invited user' do - patch 'web_api/v1/ideas/:idea_id/cosponsorships/:cosponsorship_id/accept_cosponsorship' do + patch 'web_api/v1/ideas/:idea_id/cosponsorships/:cosponsorship_id/accept' do example_request 'Accept a cosponsorship when the user is not the invited user' do expect(status).to eq 401 end diff --git a/front/app/api/cosponsorship/useAcceptCosponsorshipInvitation.test.ts b/front/app/api/cosponsorship/useAcceptCosponsorshipInvitation.test.ts index 384e34ab4c54..9e1580ec565e 100644 --- a/front/app/api/cosponsorship/useAcceptCosponsorshipInvitation.test.ts +++ b/front/app/api/cosponsorship/useAcceptCosponsorshipInvitation.test.ts @@ -7,7 +7,7 @@ import createQueryClientWrapper from 'utils/testUtils/queryClientWrapper'; import { cosponsorshipData } from './__mocks__/useCosponsorships'; import useAcceptCosponsorshipInvitation from './useAcceptCosponsorshipInvitation'; -const apiPath = '*cosponsorships/:id/accept_cosponsorship'; +const apiPath = '*cosponsorships/:id/accept'; const server = setupServer( http.patch(apiPath, () => { return HttpResponse.json({ data: cosponsorshipData[0] }, { status: 200 }); diff --git a/front/app/api/cosponsorship/useAcceptCosponsorshipInvitation.ts b/front/app/api/cosponsorship/useAcceptCosponsorshipInvitation.ts index 39d1b0581bc9..b7c9037cbf9b 100644 --- a/front/app/api/cosponsorship/useAcceptCosponsorshipInvitation.ts +++ b/front/app/api/cosponsorship/useAcceptCosponsorshipInvitation.ts @@ -16,7 +16,7 @@ const acceptCosponsorshipInvitation = ({ id, }: IAcceptCosponsorshipInvitationObject) => fetcher({ - path: `/ideas/${ideaId}/cosponsorships/${id}/accept_cosponsorship`, + path: `/ideas/${ideaId}/cosponsorships/${id}/accept`, action: 'patch', }); From aa299167ffcb693742b79e5c6aefa83a9d5c231a Mon Sep 17 00:00:00 2001 From: Iva Date: Fri, 27 Sep 2024 17:18:38 +0300 Subject: [PATCH 41/43] Fix cosponsors in form implementation --- back/lib/participation_method/ideation.rb | 2 +- back/lib/participation_method/proposals.rb | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/back/lib/participation_method/ideation.rb b/back/lib/participation_method/ideation.rb index 5f438eef9242..8c0ab155b6df 100644 --- a/back/lib/participation_method/ideation.rb +++ b/back/lib/participation_method/ideation.rb @@ -37,7 +37,7 @@ def budget_in_form?(user) end def cosponsors_in_form? - phase ? phase.participation_method == 'proposals' : false + false end # Locks mirror the name of the fields whose default values cannot be changed (ie are locked) diff --git a/back/lib/participation_method/proposals.rb b/back/lib/participation_method/proposals.rb index 5e294f7f146f..99aad481a3af 100644 --- a/back/lib/participation_method/proposals.rb +++ b/back/lib/participation_method/proposals.rb @@ -18,6 +18,10 @@ def budget_in_form?(_) false end + def cosponsors_in_form? + true + end + def supports_automated_statuses? true end From a3c3aaf9a9216c01e6f44f512d7338fdb9d4e677 Mon Sep 17 00:00:00 2001 From: Iva Date: Fri, 27 Sep 2024 17:21:40 +0300 Subject: [PATCH 42/43] Add comment to useUserWithIds hook --- front/app/api/users/useUsersByIds.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/front/app/api/users/useUsersByIds.ts b/front/app/api/users/useUsersByIds.ts index 6bec800a4657..58d4f48b5c76 100644 --- a/front/app/api/users/useUsersByIds.ts +++ b/front/app/api/users/useUsersByIds.ts @@ -14,6 +14,12 @@ export const fetchUser = (id: string) => { }); }; +/** + * Fetches users by their ids one by one (careful with performance implications) + * @param userIds - Array of user ids + * @returns Array of useQuery hooks + */ + const useUsersWithIds = (userIds?: string[]) => { const queries = userIds ? userIds.map((userId) => ({ From 4b3c37bb79d03a8eda3a0594bc120a06311582d3 Mon Sep 17 00:00:00 2001 From: Iva Date: Fri, 27 Sep 2024 17:23:42 +0300 Subject: [PATCH 43/43] Fix scope again --- back/app/policies/cosponsorship_policy.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/back/app/policies/cosponsorship_policy.rb b/back/app/policies/cosponsorship_policy.rb index f38b90f399dd..f0ad364c4b03 100644 --- a/back/app/policies/cosponsorship_policy.rb +++ b/back/app/policies/cosponsorship_policy.rb @@ -10,7 +10,7 @@ def initialize(user, scope) end def resolve - scope.where(post_id: Pundit.policy_scope(user, Idea)) + scope.where(idea_id: Pundit.policy_scope(user, Idea)) end end