diff --git a/app/controllers/api/v1/accounts/portals_controller.rb b/app/controllers/api/v1/accounts/portals_controller.rb index 7f43766d2..b12f89c0a 100644 --- a/app/controllers/api/v1/accounts/portals_controller.rb +++ b/app/controllers/api/v1/accounts/portals_controller.rb @@ -23,7 +23,7 @@ class Api::V1::Accounts::PortalsController < Api::V1::Accounts::BaseController def update ActiveRecord::Base.transaction do - @portal.update!(portal_params.merge(live_chat_widget_params)) if params[:portal].present? + @portal.update!(merged_portal_params.merge(live_chat_widget_params)) if params[:portal].present? # @portal.custom_domain = parsed_custom_domain process_attached_logo if params[:blob_id].present? rescue ActiveRecord::RecordInvalid => e @@ -79,10 +79,20 @@ class Api::V1::Accounts::PortalsController < Api::V1::Accounts::BaseController def portal_params params.require(:portal).permit( :id, :color, :custom_domain, :header_text, :homepage_link, - :name, :page_title, :slug, :archived, { config: [:default_locale, { allowed_locales: [] }] } + :name, :page_title, :slug, :archived, { config: [:default_locale, :show_author, { allowed_locales: [] }] } ) end + def merged_portal_params + update_params = portal_params.to_h + if update_params.key?('config') + base_config = @portal.config.is_a?(Hash) ? @portal.config : {} + incoming_config = update_params['config'] + update_params['config'] = incoming_config.is_a?(Hash) ? base_config.merge(incoming_config) : base_config + end + update_params + end + def live_chat_widget_params permitted_params = params.permit(:inbox_id) return {} unless permitted_params.key?(:inbox_id) diff --git a/app/javascript/dashboard/components-next/HelpCenter/Pages/PortalSettingsPage/PortalBaseSettings.vue b/app/javascript/dashboard/components-next/HelpCenter/Pages/PortalSettingsPage/PortalBaseSettings.vue index b99f08a29..3258162dc 100644 --- a/app/javascript/dashboard/components-next/HelpCenter/Pages/PortalSettingsPage/PortalBaseSettings.vue +++ b/app/javascript/dashboard/components-next/HelpCenter/Pages/PortalSettingsPage/PortalBaseSettings.vue @@ -15,6 +15,7 @@ import Input from 'dashboard/components-next/input/Input.vue'; import Avatar from 'dashboard/components-next/avatar/Avatar.vue'; import ComboBox from 'dashboard/components-next/combobox/ComboBox.vue'; import ColorPicker from 'dashboard/components-next/colorpicker/ColorPicker.vue'; +import Switch from 'dashboard/components-next/switch/Switch.vue'; const props = defineProps({ activePortal: { @@ -45,6 +46,7 @@ const state = reactive({ liveChatWidgetInboxId: '', logoUrl: '', avatarBlobId: '', + showAuthor: true, }); const originalState = reactive({ ...state }); @@ -117,6 +119,7 @@ watch( homePageLink: newVal.homepage_link, slug: newVal.slug, liveChatWidgetInboxId: newVal.inbox?.id || '', + showAuthor: newVal.config?.show_author !== false, }); if (newVal.logo) { const { @@ -149,6 +152,7 @@ const handleUpdatePortal = () => { homepage_link: state.homePageLink, blob_id: state.avatarBlobId, inbox_id: state.liveChatWidgetInboxId, + config: { show_author: state.showAuthor }, }; emit('updatePortal', portal); }; @@ -335,6 +339,21 @@ const handleAvatarDelete = () => { +
+ +
+ + + {{ t('HELP_CENTER.PORTAL_SETTINGS.FORM.SHOW_AUTHOR.HELP_TEXT') }} + +
+
+ <% if portal.show_author? %> <%= render "public/api/v1/portals/authors", category: category, show_expanded: false %> + <% end %> <%= render 'public/api/v1/portals/article_count', article_count: category.articles.published.order(position: :asc).size %>
diff --git a/app/views/public/api/v1/portals/categories/_category-hero.html.erb b/app/views/public/api/v1/portals/categories/_category-hero.html.erb index c0b87d82c..d2f808ce5 100644 --- a/app/views/public/api/v1/portals/categories/_category-hero.html.erb +++ b/app/views/public/api/v1/portals/categories/_category-hero.html.erb @@ -22,8 +22,10 @@ <% end %>
+ <% if portal.show_author? %> <%= render "public/api/v1/portals/authors", category: category, show_expanded: true %> + <% end %> <%= render 'public/api/v1/portals/article_count', article_count: category.articles.published.size %>
diff --git a/spec/controllers/api/v1/accounts/portals_controller_spec.rb b/spec/controllers/api/v1/accounts/portals_controller_spec.rb index c8e5c653c..a21be237a 100644 --- a/spec/controllers/api/v1/accounts/portals_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/portals_controller_spec.rb @@ -131,7 +131,49 @@ RSpec.describe 'Api::V1::Accounts::Portals', type: :request do json_response = response.parsed_body expect(json_response['name']).to eql(portal_params[:portal][:name]) expect(json_response['config']).to eql({ 'allowed_locales' => [{ 'articles_count' => 0, 'categories_count' => 0, 'code' => 'en' }, - { 'articles_count' => 0, 'categories_count' => 0, 'code' => 'es' }] }) + { 'articles_count' => 0, 'categories_count' => 0, 'code' => 'es' }], + 'show_author' => true }) + end + + it 'persists show_author as false when explicitly set' do + put "/api/v1/accounts/#{account.id}/portals/#{portal.slug}", + params: { portal: { config: { show_author: false } } }, + headers: admin.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + json_response = response.parsed_body + expect(json_response['config']['show_author']).to be(false) + + portal.reload + expect(portal.show_author?).to be(false) + end + + it 'preserves show_author when updating other portal fields' do + portal.update!(config: portal.config.merge('show_author' => false)) + + put "/api/v1/accounts/#{account.id}/portals/#{portal.slug}", + params: { portal: { name: 'renamed_portal' } }, + headers: admin.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + portal.reload + expect(portal.show_author?).to be(false) + expect(portal.name).to eql('renamed_portal') + end + + it 'preserves show_author when updating only allowed_locales' do + portal.update!(config: portal.config.merge('show_author' => false)) + + put "/api/v1/accounts/#{account.id}/portals/#{portal.slug}", + params: { portal: { config: { allowed_locales: %w[en fr] } } }, + headers: admin.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + portal.reload + expect(portal.show_author?).to be(false) end it 'archive portal' do