| defmodule PlausibleWeb.Live.Components.Verification do |
| @moduledoc """ |
| This component is responsible for rendering the verification progress |
| and diagnostics. |
| """ |
| use Phoenix.LiveComponent |
| use Plausible |
|
|
| alias PlausibleWeb.Router.Helpers, as: Routes |
| alias Plausible.InstallationSupport.{State, Result} |
|
|
| import PlausibleWeb.Components.Generic |
|
|
| attr(:domain, :string, required: true) |
|
|
| attr(:message, :string, |
| default: "We're visiting your site to ensure that everything is working" |
| ) |
|
|
| attr(:super_admin?, :boolean, default: false) |
| attr(:finished?, :boolean, default: false) |
| attr(:success?, :boolean, default: false) |
| attr(:verification_state, State, default: nil) |
| attr(:interpretation, Result, default: nil) |
| attr(:attempts, :integer, default: 0) |
| attr(:flow, :string, default: "") |
| attr(:installation_type, :string, default: nil) |
| attr(:awaiting_first_pageview?, :boolean, default: false) |
|
|
| def render(assigns) do |
| ~H""" |
| <div id="verification-ui"> |
| <.render_progress :if={not @finished?} message={@message} /> |
| <.render_success |
| :if={@finished? and @success?} |
| awaiting_first_pageview?={@awaiting_first_pageview?} |
| domain={@domain} |
| /> |
| <.render_failed |
| :if={@finished? and not @success?} |
| interpretation={@interpretation} |
| attempts={@attempts} |
| domain={@domain} |
| flow={@flow} |
| installation_type={@installation_type} |
| /> |
| <.render_super_admin_diagnostics |
| :if={not is_nil(@verification_state) && @super_admin? && @finished?} |
| verification_state={@verification_state} |
| /> |
| </div> |
| """ |
| end |
|
|
| defp render_progress(assigns) do |
| ~H""" |
| <.focus_box> |
| <div class="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-green-100 dark:bg-gray-700"> |
| <div class="block pulsating-circle"></div> |
| </div> |
| <div class="mt-8"> |
| <.title>Verifying your installation</.title> |
| <p class="text-sm mt-4 animate-pulse" id="progress">{@message}</p> |
| </div> |
| </.focus_box> |
| """ |
| end |
|
|
| defp render_success(assigns) do |
| ~H""" |
| <.focus_box> |
| <div |
| class="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-green-100 dark:bg-green-500" |
| id="check-circle" |
| > |
| <Heroicons.check_badge class="h-6 w-6 text-green-600 bg-green-100 dark:bg-green-500 dark:text-green-200" /> |
| </div> |
| |
| <div class="mt-8"> |
| <.title>Success!</.title> |
| <p class="text-sm mt-4"> |
| Your installation is working and visitors are being counted accurately. |
| <span :if={@awaiting_first_pageview?} id="awaiting" class="text-sm mt-4 animate-pulse"> |
| Awaiting your first pageview... |
| </span> |
| </p> |
| </div> |
| <.button_link |
| href={"/ |
| class="w-full font-bold mb-4" |
| > |
| Go to the dashboard |
| </.button_link> |
| </.focus_box> |
| """ |
| end |
| |
| defp render_failed(assigns) do |
| ~H""" |
| <.focus_box> |
| <div |
| class="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-red-100 dark:bg-red-200" |
| id="error-circle" |
| > |
| <Heroicons.exclamation_triangle class="h-6 w-6 text-red-600 bg-red-100 dark:bg-red-200 dark:text-red-800" /> |
| </div> |
|
|
| <div :if={@interpretation} class="mt-8"> |
| <.title>{List.first(@interpretation.errors)}</.title> |
| <p id="recommendation" class="mt-4 text-sm text-ellipsis overflow-hidden"> |
| <span>{List.first(@interpretation.recommendations).text}. </span> |
| <.styled_link href={List.first(@interpretation.recommendations).url} new_tab={true}> |
| Learn more |
| </.styled_link> |
| </p> |
| </div> |
|
|
| <div class="mt-6"> |
| <.button_link mt?={false} href="#" phx-click="retry" class="w-full"> |
| Verify installation again |
| </.button_link> |
| </div> |
| <:footer> |
| <.focus_list> |
| <:item :if={ |
| @interpretation && is_map(@interpretation.data) && |
| @interpretation.data[:offer_custom_url_input] |
| }> |
| <span id="verify-custom-url-link"> |
| Is your website located at a different URL? |
| <.styled_link href={ |
| Routes.site_path(PlausibleWeb.Endpoint, :verification, @domain, |
| flow: @flow, |
| installation_type: @installation_type, |
| custom_url: true |
| ) |
| }> |
| Click here |
| </.styled_link> |
| </span> |
| </:item> |
| <:item :if={ee?() and @attempts >= 3}> |
| <b>Need further help with your installation?</b> |
| <.styled_link href="https://plausible.io/contact"> |
| Contact us |
| </.styled_link> |
| </:item> |
| <:item> |
| Need to see installation instructions again? |
| <.styled_link href={ |
| Routes.site_path(PlausibleWeb.Endpoint, :installation, @domain, |
| flow: @flow, |
| installation_type: @installation_type |
| ) |
| }> |
| Click here |
| </.styled_link> |
| </:item> |
| <:item> |
| Run verification later and go to site settings? |
| <.styled_link href={"/#{URI.encode_www_form(@domain)}/settings/general"}> |
| Click here |
| </.styled_link> |
| </:item> |
| </.focus_list> |
| </:footer> |
| </.focus_box> |
| """ |
| end |
| |
| defp render_super_admin_diagnostics(assigns) do |
| ~H""" |
| <.focus_box> |
| <div |
| class="flex flex-col dark:text-gray-200" |
| x-data="{ showDiagnostics: false }" |
| id="super-admin-report" |
| > |
| <p class="text-sm"> |
| <a |
| href="#" |
| @click.prevent="showDiagnostics = !showDiagnostics" |
| class="bg-yellow-100 dark:bg-yellow-800/40" |
| > |
| As a super-admin, you're eligible to see diagnostics details. Click to expand. |
| </a> |
| </p> |
| <div x-show="showDiagnostics" x-cloak> |
| <.focus_list> |
| <:item :for={{diag, value} <- Map.from_struct(@verification_state.diagnostics)}> |
| <span class="text-sm"> |
| {Phoenix.Naming.humanize(diag)}: |
| <span class="font-mono">{to_string_value(value)}</span> |
| </span> |
| </:item> |
| </.focus_list> |
| </div> |
| </div> |
| </.focus_box> |
| """ |
| end |
| |
| defp to_string_value(value) when is_binary(value), do: value |
| defp to_string_value(value), do: inspect(value) |
| end |
| |