diff --git a/app/components/checkbox/checkbox.html.erb b/app/components/checkbox/checkbox.html.erb index 0174fc3dd..2b09a60fd 100644 --- a/app/components/checkbox/checkbox.html.erb +++ b/app/components/checkbox/checkbox.html.erb @@ -6,4 +6,5 @@ value='1' <%= checked ? 'checked' : '' %> <%= required ? 'required' : '' %> + <%= attrs %> /> \ No newline at end of file diff --git a/app/components/onboarding_channels_checkboxes/onboarding_channels_checkboxes.css b/app/components/onboarding_channels_checkboxes/onboarding_channels_checkboxes.css new file mode 100644 index 000000000..7574e97a9 --- /dev/null +++ b/app/components/onboarding_channels_checkboxes/onboarding_channels_checkboxes.css @@ -0,0 +1,29 @@ +.OnboardingChannelsCheckboxes { + border: 0; +} + +.OnboardingChannelsCheckboxes-legend { + display: block; + font-weight: 600; + font-size: var(--font-size); +} + +.OnboardingChannelsCheckboxes-helpText { + font-size: var(--font-size-s); + color: var(--color-text-light); +} + +.OnboardingChannelsCheckboxes-list { + list-style: none; + display: flex; + justify-content: space-between; +} + +.OnboardingChannelsCheckboxes-listItem { + display: flex; + align-items: center; +} + +.OnboardingChannelsCheckboxes-listItem > .Checkbox { + margin-right: var(--spacing-unit-xs); +} diff --git a/app/components/onboarding_channels_checkboxes/onboarding_channels_checkboxes.html.erb b/app/components/onboarding_channels_checkboxes/onboarding_channels_checkboxes.html.erb new file mode 100644 index 000000000..c1816737d --- /dev/null +++ b/app/components/onboarding_channels_checkboxes/onboarding_channels_checkboxes.html.erb @@ -0,0 +1,16 @@ +
diff --git a/app/components/onboarding_channels_checkboxes/onboarding_channels_checkboxes.rb b/app/components/onboarding_channels_checkboxes/onboarding_channels_checkboxes.rb new file mode 100644 index 000000000..ce503df61 --- /dev/null +++ b/app/components/onboarding_channels_checkboxes/onboarding_channels_checkboxes.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +module OnboardingChannelsCheckboxes + class OnboardingChannelsCheckboxes < ApplicationComponent; end +end diff --git a/app/components/settings_form/settings_form.css b/app/components/settings_form/settings_form.css new file mode 100644 index 000000000..b1bfe474b --- /dev/null +++ b/app/components/settings_form/settings_form.css @@ -0,0 +1,10 @@ +.SettingsForm { + padding-left: var(--limit-max-inner-width); + padding-right: var(--limit-max-inner-width); + margin: var(--spacing-unit) 0; +} + +.SettingsForm .Section { + padding-left: 0; + padding-right: 0; +} diff --git a/app/components/settings_form/settings_form.html.erb b/app/components/settings_form/settings_form.html.erb index 643d96360..d9d09b050 100644 --- a/app/components/settings_form/settings_form.html.erb +++ b/app/components/settings_form/settings_form.html.erb @@ -1,78 +1,76 @@ -<%= c 'form', model: Setting.new, multipart: true do %> - <%= c 'stack', space: :xlarge do %> +<%= c 'form', model: Setting.new, multipart: true, **attrs do %> + <%= c 'section' do %> + <%= c('heading', tag: :h2) { t('setting.form.groups.project_settings') } %> + <%= c('settings_field', type: :input, attr: :project_name) %> + <% end %> - <%= c 'stack' do %> - <%= c('heading', tag: :h2) { t('setting.form.groups.project_settings') } %> - <%= c('settings_field', type: :input, attr: :project_name) %> + <%= c 'section' do %> + <%= c('heading', tag: :h2) { t('setting.form.groups.onboarding') } %> + <%= c('settings_field', type: :image_input, attr: :onboarding_logo) %> + <%= c('settings_field', type: :input, attr: :onboarding_byline) %> + <%= c('settings_field', type: :image_input, attr: :onboarding_hero) %> + <%= c('settings_field', type: :input, attr: :onboarding_title) %> + <%= c('settings_field', type: :textarea, attr: :onboarding_page) %> + <% if current_user.admin? %> + <%= c 'onboarding_channels_checkboxes' %> + <%= c('settings_field', type: :url_input, attr: :onboarding_data_protection_link) %> + <%= c('settings_field', type: :textarea, attr: :onboarding_data_processing_consent_additional_info) %> + <%= c('settings_field', type: :url_input, attr: :onboarding_imprint_link) %> <% end %> + <% end %> + <% if current_user.admin? %> <%= c 'stack' do %> - <%= c('heading', tag: :h2) { t('setting.form.groups.onboarding') } %> - <%= c('settings_field', type: :image_input, attr: :onboarding_logo) %> - <%= c('settings_field', type: :input, attr: :onboarding_byline) %> - <%= c('settings_field', type: :image_input, attr: :onboarding_hero) %> - <%= c('settings_field', type: :input, attr: :onboarding_title) %> - <%= c('settings_field', type: :textarea, attr: :onboarding_page) %> - <% if current_user.admin? %> - <%= c('settings_field', type: :url_input, attr: :onboarding_data_protection_link) %> - <%= c('settings_field', type: :textarea, attr: :onboarding_data_processing_consent_additional_info) %> - <%= c('settings_field', type: :url_input, attr: :onboarding_imprint_link) %> - <% end %> - <% end %> - - <% if current_user.admin? %> - <%= c 'stack' do %> - <%= c('heading', tag: :h2) { t 'setting.form.groups.onboarding_additional_consent' } %> + <%= c('heading', tag: :h2) { t 'setting.form.groups.onboarding_additional_consent' } %> - <%= c('field', - object: Setting.new, - attr: :onboarding_ask_for_additional_consent, - styles: [:horizontal, :leftAligned], - ) do |field| %> - <%= c 'checkbox', **field.input_defaults, checked: Setting.onboarding_ask_for_additional_consent %> - <% end %> - - <%= c('settings_field', type: :input, attr: :onboarding_additional_consent_heading) %> - <%= c('settings_field', type: :input, attr: :onboarding_additional_consent_text) %> + <%= c('field', + object: Setting.new, + attr: :onboarding_ask_for_additional_consent, + styles: [:horizontal, :leftAligned], + ) do |field| %> + <%= c 'checkbox', **field.input_defaults, checked: Setting.onboarding_ask_for_additional_consent %> <% end %> - <% end %> - <%= c 'stack' do %> - <%= c('heading', tag: :h2) { t('setting.form.groups.onboarding_success') } %> - <%= c('settings_field', type: :input, attr: :onboarding_success_heading) %> - <%= c('settings_field', type: :textarea, attr: :onboarding_success_text) %> + <%= c('settings_field', type: :input, attr: :onboarding_additional_consent_heading) %> + <%= c('settings_field', type: :input, attr: :onboarding_additional_consent_text) %> <% end %> + <% end %> - <%= c 'stack' do %> - <%= c('heading', tag: :h2) { t('setting.form.groups.onboarding_unauthorized') } %> - <%= c('settings_field', type: :input, attr: :onboarding_unauthorized_heading) %> - <%= c('settings_field', type: :textarea, attr: :onboarding_unauthorized_text) %> - <% end %> + <%= c 'stack' do %> + <%= c('heading', tag: :h2) { t('setting.form.groups.onboarding_success') } %> + <%= c('settings_field', type: :input, attr: :onboarding_success_heading) %> + <%= c('settings_field', type: :textarea, attr: :onboarding_success_text) %> + <% end %> - <%= c 'stack' do %> - <%= c('heading', tag: :h2) { t('setting.form.groups.signal') } %> - <%= c('settings_field', type: :textarea, attr: :signal_unknown_content_message) %> - <% end %> + <%= c 'stack' do %> + <%= c('heading', tag: :h2) { t('setting.form.groups.onboarding_unauthorized') } %> + <%= c('settings_field', type: :input, attr: :onboarding_unauthorized_heading) %> + <%= c('settings_field', type: :textarea, attr: :onboarding_unauthorized_text) %> + <% end %> - <%= c 'stack' do %> - <%= c('heading', tag: :h2) { t('setting.form.groups.telegram') } %> - <%= c('settings_field', type: :textarea, attr: :telegram_unknown_content_message) %> - <%= c('settings_field', type: :textarea, attr: :telegram_contributor_not_found_message) %> - <% end %> + <%= c 'stack' do %> + <%= c('heading', tag: :h2) { t('setting.form.groups.signal') } %> + <%= c('settings_field', type: :textarea, attr: :signal_unknown_content_message) %> + <% end %> - <%= c 'stack' do %> - <%= c('heading', tag: :h2) { t('setting.form.groups.threema') } %> - <%= c('settings_field', type: :textarea, attr: :threema_unknown_content_message) %> - <% end %> + <%= c 'stack' do %> + <%= c('heading', tag: :h2) { t('setting.form.groups.telegram') } %> + <%= c('settings_field', type: :textarea, attr: :telegram_unknown_content_message) %> + <%= c('settings_field', type: :textarea, attr: :telegram_contributor_not_found_message) %> + <% end %> - <% if current_user.admin? %> - <%= c 'stack' do %> - <%= c('heading', tag: :h2) { t('setting.form.groups.all') } %> - <%= c('settings_field', type: :image_input, attr: :channel_image) %> - <%= c('settings_field', type: :textarea, attr: :about) %> - <% end %> - <% end %> + <%= c 'stack' do %> + <%= c('heading', tag: :h2) { t('setting.form.groups.threema') } %> + <%= c('settings_field', type: :textarea, attr: :threema_unknown_content_message) %> + <% end %> - <%= c 'submit_button', label: t('save') %> + <% if current_user.admin? %> + <%= c 'stack' do %> + <%= c('heading', tag: :h2) { t('setting.form.groups.all') } %> + <%= c('settings_field', type: :image_input, attr: :channel_image) %> + <%= c('settings_field', type: :textarea, attr: :about) %> + <% end %> <% end %> + + <%= c 'submit_button', label: t('save') %> <% end %> diff --git a/app/controllers/onboarding_controller.rb b/app/controllers/onboarding_controller.rb index 5ddd7f855..e57379536 100644 --- a/app/controllers/onboarding_controller.rb +++ b/app/controllers/onboarding_controller.rb @@ -13,9 +13,7 @@ class OnboardingController < ApplicationController def index @jwt = jwt_param - @channels = %w[threema telegram email] - @channels << 'signal' if Setting.signal_server_phone_number.present? - @channels << 'whats_app' if Setting.whats_app_server_phone_number.present? + @channels = Setting.channels.select { |_key, value| value == true }.keys end def success; end diff --git a/app/controllers/settings_controller.rb b/app/controllers/settings_controller.rb index 31ea911e9..d446c5ccf 100644 --- a/app/controllers/settings_controller.rb +++ b/app/controllers/settings_controller.rb @@ -15,6 +15,11 @@ def update Setting.send("#{key}=", blob) end + settings_channel_param.each do |key, values_params| + values_hash = values_params.to_h.transform_values { |value| ActiveModel::Type::Boolean.new.cast(value) } + Setting.send("#{key}=", values_hash) + end + flash[:success] = I18n.t('settings.success') redirect_to settings_url end @@ -52,4 +57,8 @@ def settings_params :about ) end + + def settings_channel_param + params.require(:setting).permit(channels: {}) + end end diff --git a/app/models/setting.rb b/app/models/setting.rb index 06fcddd97..a4f5bbe77 100644 --- a/app/models/setting.rb +++ b/app/models/setting.rb @@ -83,4 +83,11 @@ def self.onboarding_hero=(blob) field :channel_image field :about, default: File.read(File.join('config', 'locales', 'about.txt')) + field :channels, type: :hash, default: { + threema: true, + telegram: true, + email: true, + signal: true, + whats_app: true + } end diff --git a/app/views/settings/index.html.erb b/app/views/settings/index.html.erb index f5d382131..2c3636f27 100644 --- a/app/views/settings/index.html.erb +++ b/app/views/settings/index.html.erb @@ -6,7 +6,5 @@<%= t('settings.subheading')%>
<% end %> - <%= c 'section' do %> - <%= c 'settings_form', current_user: current_user %> - <% end %> + <%= c 'settings_form', current_user: current_user %> <% end %> diff --git a/config/locales/de.yml b/config/locales/de.yml index c1f15b373..0b804f046 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -353,7 +353,9 @@ de: empty_state: no_contributors: Du hast noch keine Mitglieder, verschick du Einladungslinks. filter_active: Keine Mitglieder mit diesen Filtern gefunden - + onboarding_channels_checkboxes: + legend: Aktive Onboarding-Channel + help_text: Achtung, hier deaktivieren sie Kanäle. Teilnehmerinnen können sich nur noch auf aktiven Kanälen anmelden. mailer: unsubscribe: diff --git a/spec/system/settings/onboarding_channels_spec.rb b/spec/system/settings/onboarding_channels_spec.rb new file mode 100644 index 000000000..d9dbec141 --- /dev/null +++ b/spec/system/settings/onboarding_channels_spec.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Configuring Onboarding Channels' do + let(:admin) { create(:user, admin: true) } + let(:organization) { create(:organization) } + let(:jwt_payload) { { invite_code: SecureRandom.base64(16), action: 'onboarding', organization_id: organization.id } } + let(:jwt) do + JsonWebToken.encode(jwt_payload) + end + + it 'allows activating and deactivating onboarding channels' do + visit settings_path(as: admin) + + # All activated by default + within('.OnboardingChannelsCheckboxes') do + Setting.channels.each_key do |key| + expect(page).to have_field(key.to_s.camelize, id: "setting[channels][#{key}]", checked: true) + end + + uncheck 'Email' + end + + click_on 'Speichern' + expect(page).to have_current_path(settings_path(as: admin)) + + within('.OnboardingChannelsCheckboxes') do + Setting.channels.keys.map(&:to_sym).each do |key| + checked_status = !key.eql?(:email) + expect(page).to have_field(key.to_s.camelize, id: "setting[channels][#{key}]", checked: checked_status) + end + end + + visit onboarding_path(jwt: jwt) + + within('.OnboardingChannelButtons') do + Setting.channels.keys.map(&:to_sym).each do |key| + unless key.eql?(:email) + expect(page).to have_link(key.to_s.camelize, class: 'Button', href: "/onboarding/#{key.to_s.dasherize}?jwt=#{jwt}") + end + end + end + end +end diff --git a/spec/system/settings/settings_form_spec.rb b/spec/system/settings/settings_form_spec.rb index d8187a35e..079035a4a 100644 --- a/spec/system/settings/settings_form_spec.rb +++ b/spec/system/settings/settings_form_spec.rb @@ -8,6 +8,11 @@ it 'Exposes certain fields only to admin' do visit settings_path(as: user) + # Channels + Setting.channels.each do |key, _value| + expect(page).not_to have_field(key.to_s.camelize, id: "setting[channels][#{key}]") + end + # Data protection link expect(page).not_to have_field('Link zur Datenschutzerklärung') expect(page).not_to have_text(/Der Link wird während des Onboardings in der Fußzeile angezeigt. Vor der Anmeldung müssen neue/) @@ -31,6 +36,11 @@ user.update(admin: true) visit settings_path(as: user) + # Channels + Setting.channels.each do |key, _value| + expect(page).to have_field(key.to_s.camelize, id: "setting[channels][#{key}]") + end + # Data protection link expect(page).to have_field('Link zur Datenschutzerklärung') expect(page).to have_text(/Der Link wird während des Onboardings in der Fußzeile angezeigt. Vor der Anmeldung müssen neue/)