From fdccd3cafde879cf37211f30b7ea65ebf08cbfba Mon Sep 17 00:00:00 2001 From: Rolf Schmidt Date: Fri, 21 Jan 2022 08:54:10 +0100 Subject: [PATCH] Fixes #3924 - Add confirmation dialog on visibility change of an article or in article creation. --- ...ric_index.coffee => _generic_index.coffee} | 0 .../_modal_generic_confirm.coffee | 15 +++++ ...ffee => _modal_generic_description.coffee} | 0 ... => _modal_generic_destroy_confirm.coffee} | 18 +----- ...edit.coffee => _modal_generic_edit.coffee} | 0 ...ffee => _modal_generic_error_modal.coffee} | 0 ...y.coffee => _modal_generic_history.coffee} | 0 ...c_new.coffee => _modal_generic_new.coffee} | 0 .../article_public_confirm.coffee | 3 + .../article_action/internal.coffee | 16 ++++- .../ticket_zoom/article_new.coffee | 9 ++- ...119102815_issue3924_confirmation_dialog.rb | 36 +++++++++++ db/seeds/settings.rb | 28 ++++++++ i18n/zammad.pot | 56 +++++++++++----- spec/system/ticket/zoom_spec.rb | 64 +++++++++++++++++++ 15 files changed, 209 insertions(+), 36 deletions(-) rename app/assets/javascripts/app/controllers/_application_controller/{generic_index.coffee => _generic_index.coffee} (100%) create mode 100644 app/assets/javascripts/app/controllers/_application_controller/_modal_generic_confirm.coffee rename app/assets/javascripts/app/controllers/_application_controller/{generic_description.coffee => _modal_generic_description.coffee} (100%) rename app/assets/javascripts/app/controllers/_application_controller/{generic_destroy_confirm.coffee => _modal_generic_destroy_confirm.coffee} (61%) rename app/assets/javascripts/app/controllers/_application_controller/{generic_edit.coffee => _modal_generic_edit.coffee} (100%) rename app/assets/javascripts/app/controllers/_application_controller/{generic_error_modal.coffee => _modal_generic_error_modal.coffee} (100%) rename app/assets/javascripts/app/controllers/_application_controller/{generic_history.coffee => _modal_generic_history.coffee} (100%) rename app/assets/javascripts/app/controllers/_application_controller/{generic_new.coffee => _modal_generic_new.coffee} (100%) create mode 100644 app/assets/javascripts/app/controllers/_application_controller/article_public_confirm.coffee create mode 100644 db/migrate/20220119102815_issue3924_confirmation_dialog.rb diff --git a/app/assets/javascripts/app/controllers/_application_controller/generic_index.coffee b/app/assets/javascripts/app/controllers/_application_controller/_generic_index.coffee similarity index 100% rename from app/assets/javascripts/app/controllers/_application_controller/generic_index.coffee rename to app/assets/javascripts/app/controllers/_application_controller/_generic_index.coffee diff --git a/app/assets/javascripts/app/controllers/_application_controller/_modal_generic_confirm.coffee b/app/assets/javascripts/app/controllers/_application_controller/_modal_generic_confirm.coffee new file mode 100644 index 000000000..9b91a0183 --- /dev/null +++ b/app/assets/javascripts/app/controllers/_application_controller/_modal_generic_confirm.coffee @@ -0,0 +1,15 @@ +class App.ControllerConfirm extends App.ControllerModal + buttonClose: true + buttonCancel: true + buttonSubmit: __('Yes') + buttonClass: 'btn--danger' + head: __('Confirmation') + small: true + + content: -> + App.i18n.translateContent(@message) + + onSubmit: => + @close() + if @callback + @callback() diff --git a/app/assets/javascripts/app/controllers/_application_controller/generic_description.coffee b/app/assets/javascripts/app/controllers/_application_controller/_modal_generic_description.coffee similarity index 100% rename from app/assets/javascripts/app/controllers/_application_controller/generic_description.coffee rename to app/assets/javascripts/app/controllers/_application_controller/_modal_generic_description.coffee diff --git a/app/assets/javascripts/app/controllers/_application_controller/generic_destroy_confirm.coffee b/app/assets/javascripts/app/controllers/_application_controller/_modal_generic_destroy_confirm.coffee similarity index 61% rename from app/assets/javascripts/app/controllers/_application_controller/generic_destroy_confirm.coffee rename to app/assets/javascripts/app/controllers/_application_controller/_modal_generic_destroy_confirm.coffee index b0ef1d2ca..83177b17f 100644 --- a/app/assets/javascripts/app/controllers/_application_controller/generic_destroy_confirm.coffee +++ b/app/assets/javascripts/app/controllers/_application_controller/_modal_generic_destroy_confirm.coffee @@ -3,7 +3,7 @@ class App.ControllerGenericDestroyConfirm extends App.ControllerModal buttonCancel: true buttonSubmit: __('delete') buttonClass: 'btn--danger' - head: __('Confirm') + head: __('Confirmation') small: true content: -> @@ -19,19 +19,3 @@ class App.ControllerGenericDestroyConfirm extends App.ControllerModal @log 'errors' @showAlert(data.human_error || data.error) @item.destroy(options) - -class App.ControllerConfirm extends App.ControllerModal - buttonClose: true - buttonCancel: true - buttonSubmit: __('yes') - buttonClass: 'btn--danger' - head: __('Confirm') - small: true - - content: -> - App.i18n.translateContent(@message) - - onSubmit: => - @close() - if @callback - @callback() diff --git a/app/assets/javascripts/app/controllers/_application_controller/generic_edit.coffee b/app/assets/javascripts/app/controllers/_application_controller/_modal_generic_edit.coffee similarity index 100% rename from app/assets/javascripts/app/controllers/_application_controller/generic_edit.coffee rename to app/assets/javascripts/app/controllers/_application_controller/_modal_generic_edit.coffee diff --git a/app/assets/javascripts/app/controllers/_application_controller/generic_error_modal.coffee b/app/assets/javascripts/app/controllers/_application_controller/_modal_generic_error_modal.coffee similarity index 100% rename from app/assets/javascripts/app/controllers/_application_controller/generic_error_modal.coffee rename to app/assets/javascripts/app/controllers/_application_controller/_modal_generic_error_modal.coffee diff --git a/app/assets/javascripts/app/controllers/_application_controller/generic_history.coffee b/app/assets/javascripts/app/controllers/_application_controller/_modal_generic_history.coffee similarity index 100% rename from app/assets/javascripts/app/controllers/_application_controller/generic_history.coffee rename to app/assets/javascripts/app/controllers/_application_controller/_modal_generic_history.coffee diff --git a/app/assets/javascripts/app/controllers/_application_controller/generic_new.coffee b/app/assets/javascripts/app/controllers/_application_controller/_modal_generic_new.coffee similarity index 100% rename from app/assets/javascripts/app/controllers/_application_controller/generic_new.coffee rename to app/assets/javascripts/app/controllers/_application_controller/_modal_generic_new.coffee diff --git a/app/assets/javascripts/app/controllers/_application_controller/article_public_confirm.coffee b/app/assets/javascripts/app/controllers/_application_controller/article_public_confirm.coffee new file mode 100644 index 000000000..2f5203fc0 --- /dev/null +++ b/app/assets/javascripts/app/controllers/_application_controller/article_public_confirm.coffee @@ -0,0 +1,3 @@ +class App.ControllerArticlePublicConfirm extends App.ControllerConfirm + head: __('Publish Article') + message: __('Do you really want to set the visibility of this article to "public"?') diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/article_action/internal.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/article_action/internal.coffee index f777ee115..f88ec8354 100644 --- a/app/assets/javascripts/app/controllers/ticket_zoom/article_action/internal.coffee +++ b/app/assets/javascripts/app/controllers/ticket_zoom/article_action/internal.coffee @@ -20,6 +20,21 @@ class Internal @perform: (articleContainer, type, ticket, article, ui) -> return true if type isnt 'internal' && type isnt 'public' + if type is 'public' + if App.Config.get('ui_ticket_zoom_article_visibility_confirmation_dialog') + new App.ControllerArticlePublicConfirm( + callback: => + @change(articleContainer, article, ui) + container: ui.el.closest('.content') + ) + else + @change(articleContainer, article, ui) + else + @change(articleContainer, article, ui) + + true + + @change: (articleContainer, article, ui) -> # storage update internal = true if article.internal == true @@ -35,6 +50,5 @@ class Internal ui.render() - true App.Config.set('100-Internal', Internal, 'TicketZoomArticleAction') diff --git a/app/assets/javascripts/app/controllers/ticket_zoom/article_new.coffee b/app/assets/javascripts/app/controllers/ticket_zoom/article_new.coffee index 2931b1dfd..a05680034 100644 --- a/app/assets/javascripts/app/controllers/ticket_zoom/article_new.coffee +++ b/app/assets/javascripts/app/controllers/ticket_zoom/article_new.coffee @@ -329,7 +329,14 @@ class App.TicketZoomArticleNew extends App.Controller if @articleNewEdit.hasClass('is-public') @setArticleInternal(true) else - @setArticleInternal(false) + if App.Config.get('ui_ticket_zoom_article_visibility_confirmation_dialog') + new App.ControllerArticlePublicConfirm( + callback: => + @setArticleInternal(false) + container: $(e.target).closest('.content') + ) + else + @setArticleInternal(false) showSelectableArticleType: (event) => event.stopPropagation() diff --git a/db/migrate/20220119102815_issue3924_confirmation_dialog.rb b/db/migrate/20220119102815_issue3924_confirmation_dialog.rb new file mode 100644 index 000000000..bb703efee --- /dev/null +++ b/db/migrate/20220119102815_issue3924_confirmation_dialog.rb @@ -0,0 +1,36 @@ +# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/ + +class Issue3924ConfirmationDialog < ActiveRecord::Migration[6.0] + def change + + # return if it's a new setup + return if !Setting.exists?(name: 'system_init_done') + + Setting.create_if_not_exists( + title: __('Note - visibility confirmation dialog'), + name: 'ui_ticket_zoom_article_visibility_confirmation_dialog', + area: 'UI::TicketZoom', + description: __('Defines if the agent has to accept a confirmation dialog when changing the article visibility to "public".'), + options: { + form: [ + { + display: '', + null: true, + name: 'ui_ticket_zoom_article_visibility_confirmation_dialog', + tag: 'boolean', + options: { + true => 'yes', + false => 'no', + }, + }, + ], + }, + state: false, + preferences: { + prio: 100, + permission: ['admin.ui'], + }, + frontend: true + ) + end +end diff --git a/db/seeds/settings.rb b/db/seeds/settings.rb index 515bf3b83..dd70d65b7 100644 --- a/db/seeds/settings.rb +++ b/db/seeds/settings.rb @@ -702,6 +702,34 @@ Setting.create_if_not_exists( }, frontend: true ) + +Setting.create_if_not_exists( + title: __('Note - visibility confirmation dialog'), + name: 'ui_ticket_zoom_article_visibility_confirmation_dialog', + area: 'UI::TicketZoom', + description: __('Defines if the agent has to accept a confirmation dialog when changing the article visibility to "public".'), + options: { + form: [ + { + display: '', + null: true, + name: 'ui_ticket_zoom_article_visibility_confirmation_dialog', + tag: 'boolean', + options: { + true => 'yes', + false => 'no', + }, + }, + ], + }, + state: false, + preferences: { + prio: 100, + permission: ['admin.ui'], + }, + frontend: true +) + Setting.create_if_not_exists( title: __('Email - subject field'), name: 'ui_ticket_zoom_article_email_subject', diff --git a/i18n/zammad.pot b/i18n/zammad.pot index cca599518..36c119a91 100644 --- a/i18n/zammad.pot +++ b/i18n/zammad.pot @@ -1724,8 +1724,8 @@ msgstr "" msgid "Clone" msgstr "" -#: app/assets/javascripts/app/controllers/_application_controller/generic_description.coffee -#: app/assets/javascripts/app/controllers/_application_controller/generic_error_modal.coffee +#: app/assets/javascripts/app/controllers/_application_controller/_modal_generic_description.coffee +#: app/assets/javascripts/app/controllers/_application_controller/_modal_generic_error_modal.coffee #: app/assets/javascripts/app/controllers/_plugin/maintenance.coffee #: app/assets/javascripts/app/controllers/_settings/area_proxy.coffee #: app/assets/javascripts/app/controllers/widget/error_modal.coffee @@ -1862,7 +1862,6 @@ msgstr "" msgid "Configure Base" msgstr "" -#: app/assets/javascripts/app/controllers/_application_controller/generic_destroy_confirm.coffee #: app/assets/javascripts/app/controllers/tag.coffee #: app/assets/javascripts/app/controllers/taskbar_widget.coffee #: app/assets/javascripts/app/views/agent_ticket_view/bulk.jst.eco @@ -1873,6 +1872,11 @@ msgstr "" msgid "Confirm/submit dialog" msgstr "" +#: app/assets/javascripts/app/controllers/_application_controller/_modal_generic_confirm.coffee +#: app/assets/javascripts/app/controllers/_application_controller/_modal_generic_destroy_confirm.coffee +msgid "Confirmation" +msgstr "" + #: app/assets/javascripts/app/views/knowledge_base/delete.coffee msgid "Confirmation failed." msgstr "" @@ -2682,6 +2686,11 @@ msgstr "" msgid "Defines if the GitLab (http://www.gitlab.com) integration is enabled or not." msgstr "" +#: db/migrate/20220119102815_issue3924_confirmation_dialog.rb +#: db/seeds/settings.rb +msgid "Defines if the agent has to accept a confirmation dialog when changing the article visibility to \"public\"." +msgstr "" + #: db/seeds/settings.rb msgid "Defines if the core workflow communication should run over ajax instead of websockets." msgstr "" @@ -3120,7 +3129,7 @@ msgstr "" msgid "Department" msgstr "" -#: app/assets/javascripts/app/controllers/_application_controller/generic_description.coffee +#: app/assets/javascripts/app/controllers/_application_controller/_modal_generic_description.coffee #: app/assets/javascripts/app/views/calendar/holiday_selector.jst.eco #: app/assets/javascripts/app/views/calendar/index.jst.eco #: app/assets/javascripts/app/views/channel/chat.jst.eco @@ -3250,11 +3259,15 @@ msgstr "" msgid "Do not sign email" msgstr "" -#: app/assets/javascripts/app/controllers/_application_controller/generic_destroy_confirm.coffee +#: app/assets/javascripts/app/controllers/_application_controller/_modal_generic_destroy_confirm.coffee #: app/assets/javascripts/app/controllers/tag.coffee msgid "Do you really want to delete this object?" msgstr "" +#: app/assets/javascripts/app/controllers/_application_controller/article_public_confirm.coffee +msgid "Do you really want to set the visibility of this article to \"public\"?" +msgstr "" + #: db/seeds/object_manager_attributes.rb msgid "Domain" msgstr "" @@ -3762,7 +3775,7 @@ msgstr "" msgid "Enter your username or email address" msgstr "" -#: app/assets/javascripts/app/controllers/_application_controller/generic_error_modal.coffee +#: app/assets/javascripts/app/controllers/_application_controller/_modal_generic_error_modal.coffee #: app/assets/javascripts/app/controllers/_profile/out_of_office.coffee #: app/assets/javascripts/app/controllers/_settings/area_proxy.coffee #: app/assets/javascripts/app/controllers/ticket_zoom.coffee @@ -4582,7 +4595,7 @@ msgstr "" msgid "Hi! Which one of our products?" msgstr "" -#: app/assets/javascripts/app/controllers/_application_controller/generic_history.coffee +#: app/assets/javascripts/app/controllers/_application_controller/_modal_generic_history.coffee #: app/assets/javascripts/app/controllers/organization_profile.coffee #: app/assets/javascripts/app/controllers/ticket_zoom/sidebar_ticket.coffee #: app/assets/javascripts/app/controllers/user_profile.coffee @@ -6590,6 +6603,11 @@ msgstr "" msgid "Note - default visibility" msgstr "" +#: db/migrate/20220119102815_issue3924_confirmation_dialog.rb +#: db/seeds/settings.rb +msgid "Note - visibility confirmation dialog" +msgstr "" + #: app/assets/javascripts/app/models/email_address.coffee #: app/assets/javascripts/app/models/group.coffee #: app/assets/javascripts/app/models/job.coffee @@ -7386,6 +7404,10 @@ msgstr "" msgid "Publish" msgstr "" +#: app/assets/javascripts/app/controllers/_application_controller/article_public_confirm.coffee +msgid "Publish Article" +msgstr "" + #: app/assets/javascripts/app/views/popover/kb_generic.jst.eco msgid "Published at" msgstr "" @@ -8960,7 +8982,7 @@ msgstr "" msgid "The issue could not be saved." msgstr "" -#: app/assets/javascripts/app/controllers/_application_controller/generic_new.coffee +#: app/assets/javascripts/app/controllers/_application_controller/_modal_generic_new.coffee #: app/assets/javascripts/app/controllers/_channel/_email_signature.coffee #: app/assets/javascripts/app/controllers/agent_ticket_create.coffee #: app/assets/javascripts/app/controllers/customer_ticket_create.coffee @@ -8970,7 +8992,7 @@ msgstr "" msgid "The object could not be created." msgstr "" -#: app/assets/javascripts/app/controllers/_application_controller/generic_edit.coffee +#: app/assets/javascripts/app/controllers/_application_controller/_modal_generic_edit.coffee #: app/assets/javascripts/app/controllers/_channel/sms.coffee #: app/assets/javascripts/app/controllers/_settings/area_switch.coffee #: app/assets/javascripts/app/controllers/_settings/area_ticket_number.coffee @@ -9187,7 +9209,7 @@ msgstr "" msgid "This signature is inactive, it won't be included in the reply. Change state here" msgstr "" -#: app/assets/javascripts/app/controllers/_application_controller/generic_history.coffee +#: app/assets/javascripts/app/controllers/_application_controller/_modal_generic_history.coffee msgid "This ticket was merged into" msgstr "" @@ -9210,7 +9232,7 @@ msgstr "" msgid "Thursday" msgstr "" -#: app/assets/javascripts/app/controllers/_application_controller/generic_history.coffee +#: app/assets/javascripts/app/controllers/_application_controller/_modal_generic_history.coffee #: app/assets/javascripts/app/controllers/_manage/ticket.coffee #: app/assets/javascripts/app/controllers/_ui_element/_application_selector.coffee #: app/assets/javascripts/app/controllers/_ui_element/core_workflow_condition.coffee @@ -10442,6 +10464,7 @@ msgstr "" msgid "Yellow" msgstr "" +#: app/assets/javascripts/app/controllers/_application_controller/_modal_generic_confirm.coffee #: app/assets/javascripts/app/controllers/_ui_element/ticket_perform_action.coffee msgid "Yes" msgstr "" @@ -10933,7 +10956,7 @@ msgstr "" msgid "default" msgstr "" -#: app/assets/javascripts/app/controllers/_application_controller/generic_destroy_confirm.coffee +#: app/assets/javascripts/app/controllers/_application_controller/_modal_generic_destroy_confirm.coffee #: app/assets/javascripts/app/controllers/data_privacy.coffee #: app/assets/javascripts/app/controllers/knowledge_base/sidebar/attachments.coffee #: app/assets/javascripts/app/controllers/ticket_zoom/article_action/delete.coffee @@ -11026,7 +11049,7 @@ msgstr "" msgid "for an agent to respond" msgstr "" -#: app/assets/javascripts/app/controllers/_application_controller/generic_history.coffee +#: app/assets/javascripts/app/controllers/_application_controller/_modal_generic_history.coffee msgid "from" msgstr "" @@ -11358,7 +11381,7 @@ msgstr "" msgid "select attachment…" msgstr "" -#: app/assets/javascripts/app/controllers/_application_controller/generic_history.coffee +#: app/assets/javascripts/app/controllers/_application_controller/_modal_generic_history.coffee msgid "sent to" msgstr "" @@ -11446,7 +11469,7 @@ msgstr "" msgid "telegram personal-message" msgstr "" -#: app/assets/javascripts/app/controllers/_application_controller/generic_history.coffee +#: app/assets/javascripts/app/controllers/_application_controller/_modal_generic_history.coffee #: lib/calendar_subscriptions/tickets.rb msgid "ticket" msgstr "" @@ -11515,7 +11538,7 @@ msgstr "" msgid "updated" msgstr "" -#: app/assets/javascripts/app/controllers/_application_controller/generic_history.coffee +#: app/assets/javascripts/app/controllers/_application_controller/_modal_generic_history.coffee msgid "was merged into this ticket" msgstr "" @@ -11543,7 +11566,6 @@ msgstr "" msgid "within next (relative)" msgstr "" -#: app/assets/javascripts/app/controllers/_application_controller/generic_destroy_confirm.coffee #: app/assets/javascripts/app/controllers/_ui_element/boolean.coffee #: app/assets/javascripts/app/controllers/tag.coffee #: app/assets/javascripts/app/views/object_manager/attribute/boolean.jst.eco diff --git a/spec/system/ticket/zoom_spec.rb b/spec/system/ticket/zoom_spec.rb index 54f020df1..bf828643e 100644 --- a/spec/system/ticket/zoom_spec.rb +++ b/spec/system/ticket/zoom_spec.rb @@ -2440,4 +2440,68 @@ RSpec.describe 'Ticket zoom', type: :system do expect(ticket.reload[field_name]).to be_nil end end + + describe 'Add confirmation dialog on visibility change of an article or in article creation #3924', authenticated_as: :authenticate do + let(:ticket) { create(:ticket, group: Group.find_by(name: 'Users')) } + let(:article) { create(:ticket_article, ticket: ticket) } + + before do + visit "#ticket/zoom/#{article.ticket.id}" + end + + context 'when dialog is disabled' do + def authenticate + true + end + + it 'does set the article internal and external for existing articles' do + expect { page.find('.js-ArticleAction[data-type=internal]').click }.to change { article.reload.internal }.to(true) + expect { page.find('.js-ArticleAction[data-type=public]').click }.to change { article.reload.internal }.to(false) + end + + it 'does set the article internal and external for new article' do + page.find('.js-writeArea').click({ x: 5, y: 5 }) + expect(page).to have_css('.article-new .icon-internal') + expect(page).to have_no_css('.article-new .icon-public') + + page.find('.article-new .icon-internal').click + expect(page).to have_no_css('.article-new .icon-internal') + expect(page).to have_css('.article-new .icon-public') + + page.find('.article-new .icon-public').click + expect(page).to have_css('.article-new .icon-internal') + expect(page).to have_no_css('.article-new .icon-public') + end + end + + context 'when dialog is enabled' do + def authenticate + Setting.set('ui_ticket_zoom_article_visibility_confirmation_dialog', true) + true + end + + it 'does set the article internal and external for existing articles' do + expect { page.find('.js-ArticleAction[data-type=internal]').click }.to change { article.reload.internal }.to(true) + page.find('.js-ArticleAction[data-type=public]').click + expect(page).to have_css('.modal-dialog') + expect { find('.modal-dialog button[type=submit]').click }.to change { article.reload.internal }.to(false) + end + + it 'does set the article internal and external for new article' do + page.find('.js-writeArea').click({ x: 5, y: 5 }) + expect(page).to have_css('.article-new .icon-internal') + expect(page).to have_no_css('.article-new .icon-public') + + page.find('.article-new .icon-internal').click + expect(page).to have_css('.modal-dialog') + find('.modal-dialog button[type=submit]').click + expect(page).to have_no_css('.article-new .icon-internal') + expect(page).to have_css('.article-new .icon-public') + + page.find('.article-new .icon-public').click + expect(page).to have_css('.article-new .icon-internal') + expect(page).to have_no_css('.article-new .icon-public') + end + end + end end