From e9131ea55862a49994bb582458631179e2277d5b Mon Sep 17 00:00:00 2001 From: Pranav Raj S Date: Wed, 6 May 2020 00:10:56 +0530 Subject: [PATCH] Feature: Add web push notification permission in frontend (#766) Add webpush notification permission in frontend Co-authored-by: Sojan --- .env.example | 9 +- .rubocop.yml | 2 +- Gemfile | 3 + Gemfile.lock | 7 +- .../notification_subscription_builder.rb | 28 +++ .../notification_settings_controller.rb | 3 +- .../notification_subscriptions_controller.rb | 3 +- .../api/v1/widget/conversations_controller.rb | 2 +- .../dashboard/api/notificationSubscription.js | 9 + .../components/buttons/FormSubmitButton.vue | 6 +- app/javascript/dashboard/helper/pushHelper.js | 93 +++++++ .../dashboard/i18n/locale/en/settings.json | 22 +- .../settings/profile/EmailNotifications.vue | 114 --------- .../dashboard/settings/profile/Index.vue | 6 +- .../settings/profile/NotificationSettings.vue | 226 ++++++++++++++++++ .../store/modules/userNotificationSettings.js | 8 +- app/javascript/packs/application.js | 25 +- app/javascript/shared/mixins/configMixin.js | 3 + .../notification/email_notification_job.rb | 7 + .../notification/push_notification_job.rb | 7 + app/models/agent_bot.rb | 1 + app/models/notification.rb | 6 +- app/models/notification_subscription.rb | 5 +- app/models/user.rb | 1 + .../email_notification_service.rb | 5 +- .../notification/push_notification_service.rb | 60 ++++- .../notification_settings/show.json.jbuilder | 2 + app/views/layouts/vueapp.html.erb | 5 +- ...add_index_on_notification_subscriptions.rb | 6 + db/schema.rb | 18 +- public/sw.js | 168 +++---------- spec/actions/contact_merge_action_spec.rb | 2 +- .../v1/accounts/contacts_controller_spec.rb | 2 +- ...ification_subscriptions_controller_spec.rb | 56 ++++- spec/factories/notification_subscriptions.rb | 10 + spec/listeners/notification_listener_spec.rb | 20 +- spec/models/conversation_spec.rb | 19 +- 37 files changed, 651 insertions(+), 318 deletions(-) create mode 100644 app/builders/notification_subscription_builder.rb create mode 100644 app/javascript/dashboard/api/notificationSubscription.js create mode 100644 app/javascript/dashboard/helper/pushHelper.js delete mode 100644 app/javascript/dashboard/routes/dashboard/settings/profile/EmailNotifications.vue create mode 100644 app/javascript/dashboard/routes/dashboard/settings/profile/NotificationSettings.vue create mode 100644 app/jobs/notification/email_notification_job.rb create mode 100644 app/jobs/notification/push_notification_job.rb create mode 100644 db/migrate/20200504144712_add_index_on_notification_subscriptions.rb create mode 100644 spec/factories/notification_subscriptions.rb diff --git a/.env.example b/.env.example index 9417315d3..b80e3577d 100644 --- a/.env.example +++ b/.env.example @@ -71,14 +71,14 @@ SENTRY_DSN= # Disable if you want to write logs to a file RAILS_LOG_TO_STDOUT=true LOG_LEVEL=info -LOG_SIZE=500 +LOG_SIZE=500 # Credentials to access sidekiq dashboard in production SIDEKIQ_AUTH_USERNAME= SIDEKIQ_AUTH_PASSWORD= ### This environment variables are only required if you are setting up social media channels -#facebook +#facebook FB_VERIFY_TOKEN= FB_APP_SECRET= FB_APP_ID= @@ -101,3 +101,8 @@ CHARGEBEE_API_KEY= CHARGEBEE_SITE= CHARGEBEE_WEBHOOK_USERNAME= CHARGEBEE_WEBHOOK_PASSWORD= + +## Push Notification +## generate a new key value here : https://d3v.one/vapid-key-generator/ +# VAPID_PUBLIC_KEY= +# VAPID_PRIVATE_KEY= diff --git a/.rubocop.yml b/.rubocop.yml index 48d234ba0..8d2405e3f 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -13,7 +13,7 @@ Layout/LineLength: Metrics/ClassLength: Max: 125 RSpec/ExampleLength: - Max: 15 + Max: 25 Style/Documentation: Enabled: false Style/FrozenStringLiteralComment: diff --git a/Gemfile b/Gemfile index 997e76563..e8e2fa85b 100644 --- a/Gemfile +++ b/Gemfile @@ -80,6 +80,9 @@ gem 'sidekiq' ##-- used for single column multiple binary flags in notification settings/feature flagging --## gem 'flag_shih_tzu' +##-- Push notification service --## +gem 'webpush' + group :development do gem 'annotate' gem 'bullet' diff --git a/Gemfile.lock b/Gemfile.lock index 75127f6b4..f26503fa4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -219,6 +219,7 @@ GEM haikunator (1.1.0) hana (1.3.5) hashie (4.1.0) + hkdf (0.3.0) http-accept (1.7.0) http-cookie (1.0.3) domain_name (~> 0.5) @@ -489,6 +490,9 @@ GEM rack-proxy (>= 0.6.1) railties (>= 5.2) semantic_range (>= 2.3.0) + webpush (1.0.0) + hkdf (~> 0.2) + jwt (~> 2.0) websocket-driver (0.7.1) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.4) @@ -532,7 +536,7 @@ DEPENDENCIES letter_opener listen mini_magick - mock_redis + mock_redis! pg pry-rails puma @@ -568,6 +572,7 @@ DEPENDENCIES valid_email2 web-console webpacker + webpush wisper (= 2.0.0) RUBY VERSION diff --git a/app/builders/notification_subscription_builder.rb b/app/builders/notification_subscription_builder.rb new file mode 100644 index 000000000..05b0bf984 --- /dev/null +++ b/app/builders/notification_subscription_builder.rb @@ -0,0 +1,28 @@ +class NotificationSubscriptionBuilder + pattr_initialize [:params, :user!] + + def perform + # if multiple accounts were used to login in same browser + move_subscription_to_user if identifier_subscription && identifier_subscription.user_id != user.id + build_identifier_subscription if identifier_subscription.blank? + identifier_subscription + end + + private + + def identifier + @identifier ||= params[:subscription_attributes][:endpoint] if params[:subscription_type] == 'browser_push' + end + + def identifier_subscription + @identifier_subscription ||= NotificationSubscription.find_by(identifier: identifier) + end + + def move_subscription_to_user + @identifier_subscription.update(user_id: user.id) + end + + def build_identifier_subscription + user.notification_subscriptions.create(params.merge(identifier: identifier)) + end +end diff --git a/app/controllers/api/v1/accounts/notification_settings_controller.rb b/app/controllers/api/v1/accounts/notification_settings_controller.rb index ba6e43804..14496969d 100644 --- a/app/controllers/api/v1/accounts/notification_settings_controller.rb +++ b/app/controllers/api/v1/accounts/notification_settings_controller.rb @@ -20,10 +20,11 @@ class Api::V1::Accounts::NotificationSettingsController < Api::BaseController end def notification_setting_params - params.require(:notification_settings).permit(selected_email_flags: []) + params.require(:notification_settings).permit(selected_email_flags: [], selected_push_flags: []) end def update_flags @notification_setting.selected_email_flags = notification_setting_params[:selected_email_flags] + @notification_setting.selected_push_flags = notification_setting_params[:selected_push_flags] end end diff --git a/app/controllers/api/v1/notification_subscriptions_controller.rb b/app/controllers/api/v1/notification_subscriptions_controller.rb index 17608e793..98ff9ea7a 100644 --- a/app/controllers/api/v1/notification_subscriptions_controller.rb +++ b/app/controllers/api/v1/notification_subscriptions_controller.rb @@ -2,7 +2,8 @@ class Api::V1::NotificationSubscriptionsController < Api::BaseController before_action :set_user def create - notification_subscription = @user.notification_subscriptions.create(notification_subscription_params) + notification_subscription = NotificationSubscriptionBuilder.new(user: @user, params: notification_subscription_params).perform + render json: notification_subscription end diff --git a/app/controllers/api/v1/widget/conversations_controller.rb b/app/controllers/api/v1/widget/conversations_controller.rb index 20a14b7f8..8f8e372fe 100644 --- a/app/controllers/api/v1/widget/conversations_controller.rb +++ b/app/controllers/api/v1/widget/conversations_controller.rb @@ -4,7 +4,7 @@ class Api::V1::Widget::ConversationsController < Api::V1::Widget::BaseController before_action :set_contact def toggle_typing - head :ok if conversation.nil? + head :ok && return if conversation.nil? if permitted_params[:typing_status] == 'on' trigger_typing_event(CONVERSATION_TYPING_ON) diff --git a/app/javascript/dashboard/api/notificationSubscription.js b/app/javascript/dashboard/api/notificationSubscription.js new file mode 100644 index 000000000..23424e876 --- /dev/null +++ b/app/javascript/dashboard/api/notificationSubscription.js @@ -0,0 +1,9 @@ +import ApiClient from './ApiClient'; + +class NotificationSubscriptions extends ApiClient { + constructor() { + super('notification_subscriptions'); + } +} + +export default new NotificationSubscriptions(); diff --git a/app/javascript/dashboard/components/buttons/FormSubmitButton.vue b/app/javascript/dashboard/components/buttons/FormSubmitButton.vue index c6ec19321..d8934f675 100644 --- a/app/javascript/dashboard/components/buttons/FormSubmitButton.vue +++ b/app/javascript/dashboard/components/buttons/FormSubmitButton.vue @@ -1,6 +1,6 @@