diff --git a/src/public/modules/forms/admin/controllers/pop-up-modal.client.controller.js b/src/public/modules/forms/admin/controllers/pop-up-modal.client.controller.js index 9c3c33a776..0692194d4d 100644 --- a/src/public/modules/forms/admin/controllers/pop-up-modal.client.controller.js +++ b/src/public/modules/forms/admin/controllers/pop-up-modal.client.controller.js @@ -15,6 +15,7 @@ function PopUpModalController($uibModalInstance, externalScope) { vm.description = externalScope.description vm.confirmButtonText = externalScope.confirmButtonText vm.cancelButtonText = externalScope.cancelButtonText + vm.isImportant = externalScope.isImportant vm.cancel = $uibModalInstance.close vm.confirm = function () { diff --git a/src/public/modules/forms/admin/css/edit-form.css b/src/public/modules/forms/admin/css/edit-form.css index 38f1a362ef..25c1fa0882 100644 --- a/src/public/modules/forms/admin/css/edit-form.css +++ b/src/public/modules/forms/admin/css/edit-form.css @@ -1426,3 +1426,14 @@ a.modal-cancel-btn:hover { .pull-right { cursor: pointer; } + +.inline-padding { + /* margin is set so that the error message appears to be in the same block as the toggle options */ + margin: 0 15px; +} + +/* Spinner */ +.loading-spinner { + display: flex; + justify-content: flex-end; +} diff --git a/src/public/modules/forms/admin/directiveViews/configure-mobile.client.view.html b/src/public/modules/forms/admin/directiveViews/configure-mobile.client.view.html index 44b68cf7fc..989e0d131f 100644 --- a/src/public/modules/forms/admin/directiveViews/configure-mobile.client.view.html +++ b/src/public/modules/forms/admin/directiveViews/configure-mobile.client.view.html @@ -1,6 +1,9 @@
-
+
OTP verification
+
+ +

+
+ + + You have reached the free tier limit for SMS verification. To continue + using SMS verification, + + please arrange for billing with us + +
diff --git a/src/public/modules/forms/admin/directives/configure-mobile.client.directive.js b/src/public/modules/forms/admin/directives/configure-mobile.client.directive.js index ee0bcec6a0..7f2a4b25c3 100644 --- a/src/public/modules/forms/admin/directives/configure-mobile.client.directive.js +++ b/src/public/modules/forms/admin/directives/configure-mobile.client.directive.js @@ -1,4 +1,13 @@ 'use strict' +const { get } = require('lodash') + +const { + ADMIN_VERIFIED_SMS_STATES, +} = require('../../../../../shared/util/verification') + +const AdminMetaService = require('../../../../services/AdminMetaService') + +const { injectedVariables } = require('../../../../utils/injectedVariables') angular .module('forms') @@ -10,24 +19,89 @@ function configureMobileDirective() { 'modules/forms/admin/directiveViews/configure-mobile.client.view.html', restrict: 'E', scope: { - field: '=', + field: '<', + form: '<', name: '=', characterLimit: '=', + isLoading: '<', }, controller: [ + '$q', '$uibModal', '$scope', '$translate', - function ($uibModal, $scope, $translate) { - // Get support form link from translation json. - $translate('LINKS.SUPPORT_FORM_LINK').then((supportFormLink) => { - $scope.supportFormLink = supportFormLink - }) + 'Toastr', + function ($q, $uibModal, $scope, $translate, Toastr) { + // Get the link for onboarding the form from the translation json + $translate('LINKS.VERIFIED_SMS_SETUP_LINK').then( + (verifiedSmsSetupLink) => { + $scope.verifiedSmsSetupLink = verifiedSmsSetupLink + }, + ) + + // Formats a given string as a number by setting it to US locale. + // Concretely, this adds commas between every thousand. + const formatStringAsNumber = (num) => + Number(num).toLocaleString('en-US') + + // NOTE: This is set on scope as it is used by the UI to determine if the toggle is loading + $scope.isLoading = true + $scope.field.hasRetrievalError = false + + const formattedSmsVerificationLimit = + // Format so that it has commas; conversion is required because it's string initially + formatStringAsNumber(injectedVariables.smsVerificationLimit) + const getAdminVerifiedSmsState = (verifiedSmsCount, msgSrvcId) => { + if (msgSrvcId) { + return ADMIN_VERIFIED_SMS_STATES.hasMessageServiceId + } + if (verifiedSmsCount <= injectedVariables.smsVerificationLimit) { + return ADMIN_VERIFIED_SMS_STATES.belowLimit + } + return ADMIN_VERIFIED_SMS_STATES.limitExceeded + } + + $q.when( + AdminMetaService.getFreeSmsCountsUsedByFormAdmin($scope.form._id), + ) + .then((smsCounts) => { + $scope.verifiedSmsCount = smsCounts + $scope.adminVerifiedSmsState = getAdminVerifiedSmsState( + smsCounts, + $scope.form.msgSrvcName, + ) + // NOTE: This links into the verifiable field component and hence, is used by both email and mobile + $scope.field.hasAdminExceededSmsLimit = + $scope.adminVerifiedSmsState === + ADMIN_VERIFIED_SMS_STATES.limitExceeded + }) + .catch((error) => { + $scope.field.hasRetrievalError = true + Toastr.error( + get( + error, + 'response.data.message', + 'Sorry, an error occurred. Please refresh the page to toggle OTP verification.', + ), + ) + }) + .finally(() => ($scope.isLoading = false)) + + // Only open if the admin has sms counts below the limit. + // If the admin has counts above limit without a message id, the toggle should be disabled anyway. + // Otherwise, if the admin has a message id, just enable it without the modal $scope.openVerifiedSMSModal = function () { const isTogglingOnVerifiedSms = !$scope.field.isVerifiable - $scope.verifiedSMSModal = + const isAdminBelowLimit = + $scope.adminVerifiedSmsState === + ADMIN_VERIFIED_SMS_STATES.belowLimit + const shouldShowModal = isTogglingOnVerifiedSms && + isAdminBelowLimit && + !$scope.field.hasRetrievalError + $scope.verifiedSMSModal = + shouldShowModal && $uibModal.open({ animation: true, backdrop: 'static', @@ -39,14 +113,22 @@ function configureMobileDirective() { resolve: { externalScope: function () { return { - title: 'Verified SMS charges', - confirmButtonText: 'OK, Noted', + title: `OTP verification will be disabled at ${formattedSmsVerificationLimit} responses`, + confirmButtonText: 'Accept', description: ` - Under 10,000 form responses: Free verified SMS -

- Above 10,000 form responses: ~US$0.0395 per SMS - contact us - for billing. Forms exceeding the free tier without billing will be deactivated. + We provide SMS OTP verification for free up to ${formattedSmsVerificationLimit} responses. OTP verification will be automatically disabled when your account reaches ${formattedSmsVerificationLimit} responses. +

+ If you require OTP verification for more than ${formattedSmsVerificationLimit} responses, + please arrange advance billing with us. + +

+ Current response count: ${formatStringAsNumber( + $scope.verifiedSmsCount, + )}/${formattedSmsVerificationLimit} `, + isImportant: true, } }, }, diff --git a/src/public/modules/forms/admin/views/edit-fields.client.modal.html b/src/public/modules/forms/admin/views/edit-fields.client.modal.html index 98f1c99808..6dfd863430 100644 --- a/src/public/modules/forms/admin/views/edit-fields.client.modal.html +++ b/src/public/modules/forms/admin/views/edit-fields.client.modal.html @@ -849,6 +849,7 @@