Refactor handling of mandatory settings (#13553)

* Refactor handling of mandatory settings

* Add e2e test

* Rename controller
This commit is contained in:
Michael Kohl 2021-04-29 09:25:16 +07:00 committed by GitHub
parent 69597a6b7d
commit 3837c3a221
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 158 additions and 16 deletions

View file

@ -0,0 +1,45 @@
module Admin
module Settings
class MandatorySettingsController < Admin::ApplicationController
def create
errors = upsert_config(settings_params)
if errors.none?
Audit::Logger.log(:internal, current_user, params.dup)
redirect_to admin_config_path, notice: "Site configuration was successfully updated."
else
redirect_to admin_config_path, alert: "😭 #{errors.to_sentence}"
end
end
def upsert_config(configs)
errors = []
configs.each do |key, value|
settings_model = ::Settings::Mandatory::MAPPINGS[key.to_sym]
if value.is_a?(Array)
settings_model.public_send("#{key}=", value.reject(&:blank?)) if value.present?
else
settings_model.public_send("#{key}=", value.strip) unless value.nil?
end
rescue ActiveRecord::RecordInvalid => e
errors << e.message
next
end
errors
end
private
# NOTE: we need to override this since the controller name doesn't reflect
# the model name
def authorization_resource
::Settings::Mandatory
end
def settings_params
params.permit(::Settings::Mandatory.keys)
end
end
end
end

View file

@ -4,14 +4,6 @@ module VerifySetupCompleted
module_function
MANDATORY_CONFIGS = {
community_name: Settings::Community,
community_description: Settings::Community,
suggested_tags: SiteConfig,
suggested_users: SiteConfig
}.freeze
included do
# rubocop:disable Rails/LexicallyScopedActionFilter
before_action :verify_setup_completed, only: %i[index new edit show]
@ -23,9 +15,7 @@ module VerifySetupCompleted
end
def missing_configs
@missing_configs ||= MANDATORY_CONFIGS.reject do |config, settings_model|
settings_model.public_send(config).present?
end.keys
@missing_configs ||= Settings::Mandatory.missing
end
private

View file

@ -277,7 +277,7 @@ module ApplicationHelper
def admin_config_label(method, content = nil, model: SiteConfig)
content ||= tag.span(method.to_s.humanize)
if method.to_sym.in?(VerifySetupCompleted::MANDATORY_CONFIGS)
if method.to_sym.in?(Settings::Mandatory.keys)
required = tag.span("Required", class: "crayons-indicator crayons-indicator--critical")
content = safe_join([content, required])
end

View file

@ -0,0 +1,28 @@
module Settings
# We use this model to back the "Get Started" form of the config admin page.
class Mandatory
include ActiveModel::Naming
MAPPINGS = {
community_name: Settings::Community,
community_description: Settings::Community,
suggested_tags: SiteConfig,
suggested_users: SiteConfig
}.freeze
MAPPINGS.each do |setting, settings_model|
delegate setting, "#{setting}=", to: settings_model
end
def self.keys
MAPPINGS.keys
end
def self.missing
MAPPINGS.reject do |settings, settings_model|
settings_model.public_send(settings).present?
end.keys
end
end
end

View file

@ -33,10 +33,10 @@
class="<%= VerifySetupCompleted.setup_completed? ? "hide collapse" : "show expand" %> p-3"
aria-labelledby="getStartedHeader">
<%= form_for(SiteConfig.new, url: admin_config_path) do |f| %>
<%= form_with(url: admin_settings_mandatory_settings_path, local: true, data: { testid: "getStartedSectionForm" }) do |f| %>
<fieldset class="grid gap-4">
<% VerifySetupCompleted::MANDATORY_CONFIGS.each do |config_key, settings_model| %>
<% Settings::Mandatory::MAPPINGS.each do |config_key, settings_model| %>
<%# we need to list the config as separate fields if the data structure is a Hash %>
<% placeholder_module = Constants.const_get(settings_model.name) %>
<% if settings_model.public_send(config_key).is_a?(Hash) %>
@ -50,7 +50,7 @@
<%= a_field.text_field key,
class: "crayons-textfield",
value: settings_model.public_send(config_key)[key],
placeholder: placeholer_module::DETAILS[config_key][:placeholder] %>
placeholder: placeholder_module::DETAILS[config_key][:placeholder] %>
</div>
<% end %>
<% end %>

View file

@ -62,6 +62,7 @@ Rails.application.routes.draw do
resources :authentications, only: [:create]
resources :campaigns, only: [:create]
resources :communities, only: [:create]
resources :mandatory_settings, only: [:create]
resources :mascots, only: [:create]
resources :rate_limits, only: [:create]
resources :user_experiences, only: [:create]

View file

@ -0,0 +1,78 @@
describe('Get Started Section', () => {
beforeEach(() => {
cy.testSetup();
cy.fixture('users/adminUser.json').as('user');
cy.get('@user').then((user) => {
cy.loginUser(user);
});
});
describe('Community name setting', () => {
it('updates the community name', () => {
cy.get('@user').then(({ username }) => {
cy.visit('/admin/config');
cy.findByTestId('getStartedSectionForm').as('getStartedSectionForm');
cy.get('@getStartedSectionForm')
.get('#community_name')
.clear()
.type('Awesome community');
cy.get('@getStartedSectionForm')
.findByPlaceholderText('Confirmation text')
.type(
`My username is @${username} and this action is 100% safe and appropriate.`,
);
cy.get('@getStartedSectionForm')
.findByText('Update Site Configuration')
.click();
cy.url().should('contains', '/admin/config');
cy.findByText('Site configuration was successfully updated.').should(
'be.visible',
);
// Page reloaded so need to get a new reference to the form.
cy.findByTestId('getStartedSectionForm').as('getStartedSectionForm');
cy.get('#community_name').should('have.value', 'Awesome community');
});
});
it('updates the suggested tags', () => {
cy.get('@user').then(({ username }) => {
cy.visit('/admin/config');
cy.findByTestId('getStartedSectionForm').as('getStartedSectionForm');
cy.get('@getStartedSectionForm')
.get('#suggested_tags')
.clear()
.type('much tag, so wow');
cy.get('@getStartedSectionForm')
.findByPlaceholderText('Confirmation text')
.type(
`My username is @${username} and this action is 100% safe and appropriate.`,
);
cy.get('@getStartedSectionForm')
.findByText('Update Site Configuration')
.click();
cy.url().should('contains', '/admin/config');
cy.findByText('Site configuration was successfully updated.').should(
'be.visible',
);
// Page reloaded so need to get a new reference to the form.
cy.findByTestId('getStartedSectionForm').as('getStartedSectionForm');
cy.get('#suggested_tags').should('have.value', 'much tag,so wow');
});
});
});
});

View file

@ -8,7 +8,7 @@ RSpec.describe "Admin manages configuration", type: :system do
visit admin_config_path
end
VerifySetupCompleted::MANDATORY_CONFIGS.each do |option, _setting_model|
Settings::Mandatory::MAPPINGS.each do |option, _setting_model|
it "marks #{option} as required" do
selector = "label[for='site_config_#{option}']"
expect(first(selector).text).to include("Required")