diff --git a/VERSION_CWCTL b/VERSION_CWCTL index 18091983f..47b322c97 100644 --- a/VERSION_CWCTL +++ b/VERSION_CWCTL @@ -1 +1 @@ -3.4.0 +3.4.1 diff --git a/app/controllers/api/v1/accounts/portals_controller.rb b/app/controllers/api/v1/accounts/portals_controller.rb index 6cfed161f..18538e842 100644 --- a/app/controllers/api/v1/accounts/portals_controller.rb +++ b/app/controllers/api/v1/accounts/portals_controller.rb @@ -47,6 +47,20 @@ class Api::V1::Accounts::PortalsController < Api::V1::Accounts::BaseController head :ok end + def send_instructions + email = permitted_params[:email] + return render_could_not_create_error(I18n.t('portals.send_instructions.email_required')) if email.blank? + return render_could_not_create_error(I18n.t('portals.send_instructions.invalid_email_format')) unless valid_email?(email) + return render_could_not_create_error(I18n.t('portals.send_instructions.custom_domain_not_configured')) if @portal.custom_domain.blank? + + PortalInstructionsMailer.send_cname_instructions( + portal: @portal, + recipient_email: email + ).deliver_later + + render json: { message: I18n.t('portals.send_instructions.instructions_sent_successfully') }, status: :ok + end + def process_attached_logo blob_id = params[:blob_id] blob = ActiveStorage::Blob.find_by(id: blob_id) @@ -60,12 +74,12 @@ class Api::V1::Accounts::PortalsController < Api::V1::Accounts::BaseController end def permitted_params - params.permit(:id) + params.permit(:id, :email) end def portal_params params.require(:portal).permit( - :account_id, :color, :custom_domain, :header_text, :homepage_link, + :id, :account_id, :color, :custom_domain, :header_text, :homepage_link, :name, :page_title, :slug, :archived, { config: [:default_locale, { allowed_locales: [] }] } ) end @@ -88,4 +102,10 @@ class Api::V1::Accounts::PortalsController < Api::V1::Accounts::BaseController domain = URI.parse(@portal.custom_domain) domain.is_a?(URI::HTTP) ? domain.host : @portal.custom_domain end + + def valid_email?(email) + ValidEmail2::Address.new(email).valid? + end end + +Api::V1::Accounts::PortalsController.prepend_mod_with('Api::V1::Accounts::PortalsController') diff --git a/app/javascript/dashboard/App.vue b/app/javascript/dashboard/App.vue index 675f6ea67..0fbb20ea9 100644 --- a/app/javascript/dashboard/App.vue +++ b/app/javascript/dashboard/App.vue @@ -136,7 +136,7 @@ export default {
diff --git a/app/javascript/dashboard/api/helpCenter/portals.js b/app/javascript/dashboard/api/helpCenter/portals.js index 7c6210dbd..d65dcaf1a 100644 --- a/app/javascript/dashboard/api/helpCenter/portals.js +++ b/app/javascript/dashboard/api/helpCenter/portals.js @@ -21,6 +21,14 @@ class PortalsAPI extends ApiClient { deleteLogo(portalSlug) { return axios.delete(`${this.url}/${portalSlug}/logo`); } + + sendCnameInstructions(portalSlug, email) { + return axios.post(`${this.url}/${portalSlug}/send_instructions`, { email }); + } + + sslStatus(portalSlug) { + return axios.get(`${this.url}/${portalSlug}/ssl_status`); + } } export default PortalsAPI; diff --git a/app/javascript/dashboard/assets/scss/_woot.scss b/app/javascript/dashboard/assets/scss/_woot.scss index 66416c64c..40ca7b436 100644 --- a/app/javascript/dashboard/assets/scss/_woot.scss +++ b/app/javascript/dashboard/assets/scss/_woot.scss @@ -37,30 +37,6 @@ body { width: 100%; } -.app-wrapper { - @apply h-screen flex-grow-0 min-h-0 w-full; - - .button--fixed-top { - @apply fixed ltr:right-2 rtl:left-2 top-2 flex flex-row; - } -} - -.banner + .app-wrapper { - // Reduce the height of the dashboard to make room for the banner. - // And causing the top right green-action button to be pushed down when scrolling. - @apply h-[calc(100%-48px)]; - - .button--fixed-top { - @apply top-14; - } - - .off-canvas-content { - .button--fixed-top { - @apply top-2; - } - } -} - .tooltip { @apply bg-n-solid-2 text-n-slate-12 py-1 px-2 z-40 text-xs rounded-md max-w-96; } diff --git a/app/javascript/dashboard/components-next/HelpCenter/Pages/PortalSettingsPage/AddCustomDomainDialog.vue b/app/javascript/dashboard/components-next/HelpCenter/Pages/PortalSettingsPage/AddCustomDomainDialog.vue index b43e2f2fd..0791f0519 100644 --- a/app/javascript/dashboard/components-next/HelpCenter/Pages/PortalSettingsPage/AddCustomDomainDialog.vue +++ b/app/javascript/dashboard/components-next/HelpCenter/Pages/PortalSettingsPage/AddCustomDomainDialog.vue @@ -1,6 +1,9 @@ diff --git a/app/javascript/dashboard/components-next/HelpCenter/Pages/PortalSettingsPage/PortalSettings.vue b/app/javascript/dashboard/components-next/HelpCenter/Pages/PortalSettingsPage/PortalSettings.vue index 02b5001b9..83800e002 100644 --- a/app/javascript/dashboard/components-next/HelpCenter/Pages/PortalSettingsPage/PortalSettings.vue +++ b/app/javascript/dashboard/components-next/HelpCenter/Pages/PortalSettingsPage/PortalSettings.vue @@ -26,6 +26,8 @@ const emit = defineEmits([ 'updatePortal', 'updatePortalConfiguration', 'deletePortal', + 'refreshStatus', + 'sendCnameInstructions', ]); const { t } = useI18n(); @@ -36,6 +38,7 @@ const confirmDeletePortalDialogRef = ref(null); const currentPortalSlug = computed(() => route.params.portalSlug); const isSwitchingPortal = useMapGetter('portals/isSwitchingPortal'); +const isFetchingSSLStatus = useMapGetter('portals/isFetchingSSLStatus'); const activePortal = computed(() => { return props.portals?.find(portal => portal.slug === currentPortalSlug.value); @@ -53,6 +56,14 @@ const handleUpdatePortalConfiguration = portal => { emit('updatePortalConfiguration', portal); }; +const fetchSSLStatus = () => { + emit('refreshStatus'); +}; + +const handleSendCnameInstructions = payload => { + emit('sendCnameInstructions', payload); +}; + const openConfirmDeletePortalDialog = () => { confirmDeletePortalDialogRef.value.dialogRef.open(); }; @@ -85,7 +96,10 @@ const handleDeletePortal = () => {
diff --git a/app/javascript/dashboard/components-next/sidebar/MobileSidebarLauncher.vue b/app/javascript/dashboard/components-next/sidebar/MobileSidebarLauncher.vue new file mode 100644 index 000000000..a7265f840 --- /dev/null +++ b/app/javascript/dashboard/components-next/sidebar/MobileSidebarLauncher.vue @@ -0,0 +1,58 @@ + + +