Upgrade deps, add storybook (#4947)
* Add `<.dropdown_item>` * Make the ellipsis menu functional again * Upgrade deps so that storybook can be added * Add storybook and dropdown story * Remove lingering warnings/errors * Add color mode to storybook * Use new liveview used_input? function * Alpine improvements * Add select input to storybook * Bring back `render_form` for CRM * Configure eslint so it can see deps * Remove LiveViewTest patch * Fix test for phoenix liveview 1.0 * Build assets in prod * Fix tests * Attempt to fix lint error * Add explicit text color to input * mix format * Format after merge master * Add moduledocs * Only run storybook in production * Update storybook dependency * Mix format
This commit is contained in:
parent
32d1783604
commit
6c30f62d5d
|
|
@ -2,5 +2,10 @@
|
||||||
plugins: [Phoenix.LiveView.HTMLFormatter],
|
plugins: [Phoenix.LiveView.HTMLFormatter],
|
||||||
import_deps: [:ecto, :ecto_sql, :phoenix],
|
import_deps: [:ecto, :ecto_sql, :phoenix],
|
||||||
subdirectories: ["priv/*/migrations"],
|
subdirectories: ["priv/*/migrations"],
|
||||||
inputs: ["*.{heex,ex,exs}", "{config,lib,test,extra}/**/*.{heex,ex,exs}", "priv/*/seeds.exs"]
|
inputs: [
|
||||||
|
"*.{heex,ex,exs}",
|
||||||
|
"{config,lib,test,extra}/**/*.{heex,ex,exs}",
|
||||||
|
"priv/*/seeds.exs",
|
||||||
|
"storybook/**/*.exs"
|
||||||
|
]
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ COPY tracker ./tracker
|
||||||
COPY priv ./priv
|
COPY priv ./priv
|
||||||
COPY lib ./lib
|
COPY lib ./lib
|
||||||
COPY extra ./extra
|
COPY extra ./extra
|
||||||
|
COPY storybook ./storybook
|
||||||
|
|
||||||
RUN npm run deploy --prefix ./tracker && \
|
RUN npm run deploy --prefix ./tracker && \
|
||||||
mix assets.deploy && \
|
mix assets.deploy && \
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,9 @@
|
||||||
"import/resolver": {
|
"import/resolver": {
|
||||||
"typescript": {
|
"typescript": {
|
||||||
"alwaysTryTypes": true // always try to resolve types under `<root>@types` directory even it doesn't contain any source code, like `@types/unist`
|
"alwaysTryTypes": true // always try to resolve types under `<root>@types` directory even it doesn't contain any source code, like `@types/unist`
|
||||||
|
},
|
||||||
|
"node": {
|
||||||
|
"moduleDirectory": ["node_modules", "../deps"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"react": {
|
"react": {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
@import "tailwindcss/base";
|
||||||
|
@import "tailwindcss/components";
|
||||||
|
@import "tailwindcss/utilities";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Put your component styling within the Tailwind utilities layer.
|
||||||
|
* See the https://hexdocs.pm/phoenix_storybook/sandboxing.html guide for more info.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@layer utilities {
|
||||||
|
* {
|
||||||
|
font-family: system-ui;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,11 @@
|
||||||
|
// eslint-disable-next-line import/no-unresolved
|
||||||
import "phoenix_html"
|
import "phoenix_html"
|
||||||
import Alpine from 'alpinejs'
|
// eslint-disable-next-line import/no-unresolved
|
||||||
import { Socket } from "phoenix"
|
import { Socket } from "phoenix"
|
||||||
|
// eslint-disable-next-line import/no-unresolved
|
||||||
import { LiveSocket } from "phoenix_live_view"
|
import { LiveSocket } from "phoenix_live_view"
|
||||||
|
// eslint-disable-next-line import/no-unresolved
|
||||||
|
import Alpine from 'alpinejs'
|
||||||
|
|
||||||
let csrfToken = document.querySelector("meta[name='csrf-token']")
|
let csrfToken = document.querySelector("meta[name='csrf-token']")
|
||||||
let websocketUrl = document.querySelector("meta[name='websocket-url']")
|
let websocketUrl = document.querySelector("meta[name='websocket-url']")
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
import Alpine from 'alpinejs'
|
||||||
|
import dropdown from "./liveview/dropdown"
|
||||||
|
|
||||||
|
// If your components require any hooks or custom uploaders, or if your pages
|
||||||
|
// require connect parameters, uncomment the following lines and declare them as
|
||||||
|
// such:
|
||||||
|
//
|
||||||
|
// import * as Hooks from "./hooks";
|
||||||
|
// import * as Params from "./params";
|
||||||
|
// import * as Uploaders from "./uploaders";
|
||||||
|
|
||||||
|
// (function () {
|
||||||
|
// window.storybook = { Hooks, Params, Uploaders };
|
||||||
|
// })();
|
||||||
|
|
||||||
|
|
||||||
|
window.Alpine = Alpine
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
window.Alpine.start();
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener('alpine:init', () => {
|
||||||
|
window.Alpine.data('dropdown', dropdown)
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
window.storybook = {
|
||||||
|
LiveSocketOptions: {
|
||||||
|
dom: {
|
||||||
|
onBeforeElUpdated(from, to) {
|
||||||
|
if (from._x_dataStack) {
|
||||||
|
window.Alpine.clone(from, to)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
@ -26,9 +26,6 @@
|
||||||
"d3": "^7.9.0",
|
"d3": "^7.9.0",
|
||||||
"dayjs": "^1.11.7",
|
"dayjs": "^1.11.7",
|
||||||
"iframe-resizer": "^4.3.2",
|
"iframe-resizer": "^4.3.2",
|
||||||
"phoenix": "^1.7.2",
|
|
||||||
"phoenix_html": "^3.3.1",
|
|
||||||
"phoenix_live_view": "^0.18.18",
|
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-flatpickr": "3.10.5",
|
"react-flatpickr": "3.10.5",
|
||||||
|
|
@ -9308,17 +9305,6 @@
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/phoenix": {
|
|
||||||
"version": "1.7.2",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/phoenix_html": {
|
|
||||||
"version": "3.3.1"
|
|
||||||
},
|
|
||||||
"node_modules/phoenix_live_view": {
|
|
||||||
"version": "0.18.18",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/picocolors": {
|
"node_modules/picocolors": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,6 @@
|
||||||
"d3": "^7.9.0",
|
"d3": "^7.9.0",
|
||||||
"dayjs": "^1.11.7",
|
"dayjs": "^1.11.7",
|
||||||
"iframe-resizer": "^4.3.2",
|
"iframe-resizer": "^4.3.2",
|
||||||
"phoenix": "^1.7.2",
|
|
||||||
"phoenix_html": "^3.3.1",
|
|
||||||
"phoenix_live_view": "^0.18.18",
|
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-flatpickr": "3.10.5",
|
"react-flatpickr": "3.10.5",
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ module.exports = {
|
||||||
"max-w-screen-xl"
|
"max-w-screen-xl"
|
||||||
],
|
],
|
||||||
darkMode: 'class',
|
darkMode: 'class',
|
||||||
|
important: '.plausible',
|
||||||
theme: {
|
theme: {
|
||||||
container: {
|
container: {
|
||||||
center: true,
|
center: true,
|
||||||
|
|
@ -51,7 +52,6 @@ module.exports = {
|
||||||
plugins: [
|
plugins: [
|
||||||
require('@tailwindcss/forms'),
|
require('@tailwindcss/forms'),
|
||||||
require('@tailwindcss/aspect-ratio'),
|
require('@tailwindcss/aspect-ratio'),
|
||||||
plugin(({ addVariant }) => addVariant("phx-no-feedback", [".phx-no-feedback&", ".phx-no-feedback &"])),
|
|
||||||
plugin(({ addVariant }) => addVariant("phx-click-loading", [".phx-click-loading&", ".phx-click-loading &"])),
|
plugin(({ addVariant }) => addVariant("phx-click-loading", [".phx-click-loading&", ".phx-click-loading &"])),
|
||||||
plugin(({ addVariant }) => addVariant("phx-submit-loading", [".phx-submit-loading&", ".phx-submit-loading &"])),
|
plugin(({ addVariant }) => addVariant("phx-submit-loading", [".phx-submit-loading&", ".phx-submit-loading &"])),
|
||||||
plugin(({ addVariant }) => addVariant("phx-change-loading", [".phx-change-loading&", ".phx-change-loading &"])),
|
plugin(({ addVariant }) => addVariant("phx-change-loading", [".phx-change-loading&", ".phx-change-loading &"])),
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ config :esbuild,
|
||||||
version: "0.17.11",
|
version: "0.17.11",
|
||||||
default: [
|
default: [
|
||||||
args:
|
args:
|
||||||
~w(js/app.js js/dashboard.tsx js/embed.host.js js/embed.content.js --bundle --target=es2017 --loader:.js=jsx --outdir=../priv/static/js --define:BUILD_EXTRA=true),
|
~w(js/app.js js/storybook.js js/dashboard.tsx js/embed.host.js js/embed.content.js --bundle --target=es2017 --loader:.js=jsx --outdir=../priv/static/js --define:BUILD_EXTRA=true),
|
||||||
cd: Path.expand("../assets", __DIR__),
|
cd: Path.expand("../assets", __DIR__),
|
||||||
env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
|
env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
|
||||||
]
|
]
|
||||||
|
|
@ -34,6 +34,14 @@ config :tailwind,
|
||||||
--output=../priv/static/css/app.css
|
--output=../priv/static/css/app.css
|
||||||
),
|
),
|
||||||
cd: Path.expand("../assets", __DIR__)
|
cd: Path.expand("../assets", __DIR__)
|
||||||
|
],
|
||||||
|
storybook: [
|
||||||
|
args: ~w(
|
||||||
|
--config=tailwind.config.js
|
||||||
|
--input=css/storybook.css
|
||||||
|
--output=../priv/static/css/storybook.css
|
||||||
|
),
|
||||||
|
cd: Path.expand("../assets", __DIR__)
|
||||||
]
|
]
|
||||||
|
|
||||||
config :ua_inspector,
|
config :ua_inspector,
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ config :plausible, PlausibleWeb.Endpoint,
|
||||||
watchers: [
|
watchers: [
|
||||||
esbuild: {Esbuild, :install_and_run, [:default, ~w(--sourcemap=inline --watch)]},
|
esbuild: {Esbuild, :install_and_run, [:default, ~w(--sourcemap=inline --watch)]},
|
||||||
tailwind: {Tailwind, :install_and_run, [:default, ~w(--watch)]},
|
tailwind: {Tailwind, :install_and_run, [:default, ~w(--watch)]},
|
||||||
|
storybook_tailwind: {Tailwind, :install_and_run, [:storybook, ~w(--watch)]},
|
||||||
npm: ["--prefix", "assets", "run", "typecheck", "--", "--watch", "--preserveWatchOutput"],
|
npm: ["--prefix", "assets", "run", "typecheck", "--", "--watch", "--preserveWatchOutput"],
|
||||||
npm: [
|
npm: [
|
||||||
"run",
|
"run",
|
||||||
|
|
@ -21,7 +22,8 @@ config :plausible, PlausibleWeb.Endpoint,
|
||||||
],
|
],
|
||||||
patterns: [
|
patterns: [
|
||||||
~r{priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$},
|
~r{priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$},
|
||||||
~r"lib/plausible_web/(controllers|live|components|templates|views|plugs)/.*(ex|heex)$"
|
~r"lib/plausible_web/(controllers|live|components|templates|views|plugs)/.*(ex|heex)$",
|
||||||
|
~r"storybook/.*(exs)$"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -969,3 +969,5 @@ unless s3_disabled? do
|
||||||
exports_bucket: s3_env_value.("S3_EXPORTS_BUCKET"),
|
exports_bucket: s3_env_value.("S3_EXPORTS_BUCKET"),
|
||||||
imports_bucket: s3_env_value.("S3_IMPORTS_BUCKET")
|
imports_bucket: s3_env_value.("S3_IMPORTS_BUCKET")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
config :phoenix_storybook, enabled: env !== "prod"
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ defmodule PlausibleWeb.Live.FunnelSettings do
|
||||||
<.flash_messages flash={@flash} />
|
<.flash_messages flash={@flash} />
|
||||||
|
|
||||||
<%= if @setup_funnel? do %>
|
<%= if @setup_funnel? do %>
|
||||||
<%= live_render(
|
{live_render(
|
||||||
@socket,
|
@socket,
|
||||||
PlausibleWeb.Live.FunnelSettings.Form,
|
PlausibleWeb.Live.FunnelSettings.Form,
|
||||||
id: "funnels-form",
|
id: "funnels-form",
|
||||||
|
|
@ -56,7 +56,7 @@ defmodule PlausibleWeb.Live.FunnelSettings do
|
||||||
"domain" => @domain,
|
"domain" => @domain,
|
||||||
"funnel_id" => @funnel_id
|
"funnel_id" => @funnel_id
|
||||||
}
|
}
|
||||||
) %>
|
)}
|
||||||
<% end %>
|
<% end %>
|
||||||
<div :if={@goal_count >= Funnel.min_steps()}>
|
<div :if={@goal_count >= Funnel.min_steps()}>
|
||||||
<.live_component
|
<.live_component
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ defmodule PlausibleWeb.Live.FunnelSettings.Form do
|
||||||
class="bg-white dark:bg-gray-800 shadow-md rounded px-8 pt-6 pb-8 mb-4 mt-8"
|
class="bg-white dark:bg-gray-800 shadow-md rounded px-8 pt-6 pb-8 mb-4 mt-8"
|
||||||
>
|
>
|
||||||
<.title class="mb-6">
|
<.title class="mb-6">
|
||||||
<%= if @funnel, do: "Edit", else: "Add" %> Funnel
|
{if @funnel, do: "Edit", else: "Add"} Funnel
|
||||||
</.title>
|
</.title>
|
||||||
|
|
||||||
<.input
|
<.input
|
||||||
|
|
@ -136,7 +136,7 @@ defmodule PlausibleWeb.Live.FunnelSettings.Form do
|
||||||
length(@step_ids) > map_size(@selections_made)
|
length(@step_ids) > map_size(@selections_made)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<span><%= if @funnel, do: "Update", else: "Add" %> Funnel</span>
|
<span>{if @funnel, do: "Update", else: "Add"} Funnel</span>
|
||||||
</.button>
|
</.button>
|
||||||
</div>
|
</div>
|
||||||
</.form>
|
</.form>
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,11 @@ defmodule PlausibleWeb.Live.FunnelSettings.List do
|
||||||
<.table rows={@funnels}>
|
<.table rows={@funnels}>
|
||||||
<:tbody :let={funnel}>
|
<:tbody :let={funnel}>
|
||||||
<.td truncate>
|
<.td truncate>
|
||||||
<span class="font-medium"><%= funnel.name %></span>
|
<span class="font-medium">{funnel.name}</span>
|
||||||
</.td>
|
</.td>
|
||||||
<.td hide_on_mobile>
|
<.td hide_on_mobile>
|
||||||
<span class="text-gray-500 dark:text-gray-400">
|
<span class="text-gray-500 dark:text-gray-400">
|
||||||
<%= funnel.steps_count %>-step funnel
|
{funnel.steps_count}-step funnel
|
||||||
</span>
|
</span>
|
||||||
</.td>
|
</.td>
|
||||||
<.td actions>
|
<.td actions>
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ defmodule PlausibleWeb.HelpScoutView do
|
||||||
|
|
||||||
<%= if @conn.assigns[:error] do %>
|
<%= if @conn.assigns[:error] do %>
|
||||||
<p>
|
<p>
|
||||||
Failed to get details: <%= @error %>
|
Failed to get details: {@error}
|
||||||
</p>
|
</p>
|
||||||
<% else %>
|
<% else %>
|
||||||
<div class="status">
|
<div class="status">
|
||||||
|
|
@ -25,7 +25,7 @@ defmodule PlausibleWeb.HelpScoutView do
|
||||||
Status
|
Status
|
||||||
</p>
|
</p>
|
||||||
<p class="value">
|
<p class="value">
|
||||||
<a href={@status_link} target="_blank"><%= @status_label %></a>
|
<a href={@status_link} target="_blank">{@status_label}</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -34,13 +34,13 @@ defmodule PlausibleWeb.HelpScoutView do
|
||||||
Plan
|
Plan
|
||||||
</p>
|
</p>
|
||||||
<p class="value">
|
<p class="value">
|
||||||
<a href={@plan_link} target="_blank"><%= @plan_label %></a>
|
<a href={@plan_link} target="_blank">{@plan_label}</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="sites">
|
<div class="sites">
|
||||||
<p class="label">
|
<p class="label">
|
||||||
Owner of <b><a href={@sites_link} target="_blank"><%= @sites_count %> sites</a></b>
|
Owner of <b><a href={@sites_link} target="_blank">{@sites_count} sites</a></b>
|
||||||
</p>
|
</p>
|
||||||
<p class="value"></p>
|
<p class="value"></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -51,7 +51,7 @@ defmodule PlausibleWeb.HelpScoutView do
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="value">
|
<div class="value">
|
||||||
<%= Phoenix.HTML.Format.text_to_html(@notes, escape: true) %>
|
{PhoenixHTMLHelpers.Format.text_to_html(@notes, escape: true)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
@ -64,7 +64,7 @@ defmodule PlausibleWeb.HelpScoutView do
|
||||||
<.layout>
|
<.layout>
|
||||||
<%= if @conn.assigns[:error] do %>
|
<%= if @conn.assigns[:error] do %>
|
||||||
<p>
|
<p>
|
||||||
Failed to run search: <%= @error %>
|
Failed to run search: {@error}
|
||||||
</p>
|
</p>
|
||||||
<% else %>
|
<% else %>
|
||||||
<div class="search">
|
<div class="search">
|
||||||
|
|
@ -82,7 +82,7 @@ defmodule PlausibleWeb.HelpScoutView do
|
||||||
onclick={"loadContent('/helpscout/show?#{URI.encode_query(email: user.email, conversation_id: @conversation_id, customer_id: @customer_id)}')"}
|
onclick={"loadContent('/helpscout/show?#{URI.encode_query(email: user.email, conversation_id: @conversation_id, customer_id: @customer_id)}')"}
|
||||||
href="#"
|
href="#"
|
||||||
>
|
>
|
||||||
<%= user.email %> (<%= user.sites_count %> sites)
|
{user.email} ({user.sites_count} sites)
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
@ -160,7 +160,7 @@ defmodule PlausibleWeb.HelpScoutView do
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<%= render_slot(@inner_block) %>
|
{render_slot(@inner_block)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ end
|
||||||
|
|
||||||
defmodule Plausible.Billing.Ecto.FeatureList do
|
defmodule Plausible.Billing.Ecto.FeatureList do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Ecto type representing a list of features. This is a proxy for
|
Ecto type representing a list of features. This is a proxy for
|
||||||
`{:array, Plausible.Billing.Ecto.Feature}` and is required for Kaffy to
|
`{:array, Plausible.Billing.Ecto.Feature}` and is required for Kaffy to
|
||||||
render the HTML input correctly.
|
render the HTML input correctly.
|
||||||
"""
|
"""
|
||||||
|
|
@ -52,15 +52,8 @@ defmodule Plausible.Billing.Ecto.FeatureList do
|
||||||
for mod <- Plausible.Billing.Feature.list(), not mod.free?() do
|
for mod <- Plausible.Billing.Feature.list(), not mod.free?() do
|
||||||
[
|
[
|
||||||
{:safe, ~s(<label style="padding-right: 15px;">)},
|
{:safe, ~s(<label style="padding-right: 15px;">)},
|
||||||
Phoenix.HTML.Tag.tag(
|
{:safe,
|
||||||
:input,
|
~s(<input type="checkbox" name="#{form.name}[#{field}][]" "#{form.name}_#{field}_#{mod.name()}" value="#{mod.name()}" style="margin-right: 3px;" #{if mod in features, do: "checked", else: ""}>)},
|
||||||
name: Phoenix.HTML.Form.input_name(form, field) <> "[]",
|
|
||||||
id: Phoenix.HTML.Form.input_id(form, field, mod.name()),
|
|
||||||
type: "checkbox",
|
|
||||||
value: mod.name(),
|
|
||||||
style: "margin-right: 3px;",
|
|
||||||
checked: mod in features
|
|
||||||
),
|
|
||||||
mod.display_name(),
|
mod.display_name(),
|
||||||
{:safe, ~s(</label>)}
|
{:safe, ~s(</label>)}
|
||||||
]
|
]
|
||||||
|
|
@ -68,7 +61,7 @@ defmodule Plausible.Billing.Ecto.FeatureList do
|
||||||
|
|
||||||
[
|
[
|
||||||
{:safe, ~s(<div class="form-group">)},
|
{:safe, ~s(<div class="form-group">)},
|
||||||
Phoenix.HTML.Form.label(form, field),
|
{:safe, ~s(<label for="#{form.name}_#{field}">#{Phoenix.Naming.humanize(field)}</label>)},
|
||||||
{:safe, ~s(<div class="form-control">)},
|
{:safe, ~s(<div class="form-control">)},
|
||||||
checkboxes,
|
checkboxes,
|
||||||
{:safe, ~s(</div>)},
|
{:safe, ~s(</div>)},
|
||||||
|
|
|
||||||
|
|
@ -25,14 +25,9 @@ defmodule Plausible.Billing.Ecto.Limit do
|
||||||
|
|
||||||
[
|
[
|
||||||
{:safe, ~s(<div class="form-group">)},
|
{:safe, ~s(<div class="form-group">)},
|
||||||
Phoenix.HTML.Form.label(form, field),
|
{:safe, ~s(<label for="#{form.name}_#{field}">#{Phoenix.Naming.humanize(field)}</label>)},
|
||||||
Phoenix.HTML.Form.number_input(form, field,
|
{:safe,
|
||||||
class: "form-control",
|
~s(<input id="#{form.name}_#{field}" name="#{form.name}[#{field}]" class="form-control" value="#{value}" min="-1" type="number" />)},
|
||||||
name: "#{form.name}[#{field}]",
|
|
||||||
id: "#{form.name}_#{field}",
|
|
||||||
value: value,
|
|
||||||
min: -1
|
|
||||||
),
|
|
||||||
{:safe, ~s(<p class="help_text">Use -1 for unlimited.</p>)},
|
{:safe, ~s(<p class="help_text">Use -1 for unlimited.</p>)},
|
||||||
{:safe, ~s(</div>)}
|
{:safe, ~s(</div>)}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,6 @@ defmodule PlausibleWeb do
|
||||||
|
|
||||||
use Phoenix.Component
|
use Phoenix.Component
|
||||||
|
|
||||||
import PlausibleWeb.ErrorHelpers
|
|
||||||
import PlausibleWeb.Components.Generic
|
import PlausibleWeb.Components.Generic
|
||||||
import PlausibleWeb.Live.Components.Form
|
import PlausibleWeb.Live.Components.Form
|
||||||
alias PlausibleWeb.Router.Helpers, as: Routes
|
alias PlausibleWeb.Router.Helpers, as: Routes
|
||||||
|
|
|
||||||
|
|
@ -114,12 +114,12 @@ defmodule PlausibleWeb.Components.Billing do
|
||||||
class="text-sm dark:text-gray-100"
|
class="text-sm dark:text-gray-100"
|
||||||
x-bind:class={"tab === '#{@tab}' ? 'text-indigo-600 dark:text-indigo-500 font-semibold' : 'font-medium'"}
|
x-bind:class={"tab === '#{@tab}' ? 'text-indigo-600 dark:text-indigo-500 font-semibold' : 'font-medium'"}
|
||||||
>
|
>
|
||||||
<%= @name %>
|
{@name}
|
||||||
</span>
|
</span>
|
||||||
<span class="flex text-xs text-gray-500 dark:text-gray-400">
|
<span class="flex text-xs text-gray-500 dark:text-gray-400">
|
||||||
<%= if @disabled,
|
{if @disabled,
|
||||||
do: "Not available",
|
do: "Not available",
|
||||||
else: PlausibleWeb.TextHelpers.format_date_range(@date_range) %>
|
else: PlausibleWeb.TextHelpers.format_date_range(@date_range)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -152,7 +152,7 @@ defmodule PlausibleWeb.Components.Billing do
|
||||||
~H"""
|
~H"""
|
||||||
<table class="min-w-full text-gray-900 dark:text-gray-100" {@rest}>
|
<table class="min-w-full text-gray-900 dark:text-gray-100" {@rest}>
|
||||||
<tbody class="divide-y divide-gray-200 dark:divide-gray-600">
|
<tbody class="divide-y divide-gray-200 dark:divide-gray-600">
|
||||||
<%= render_slot(@inner_block) %>
|
{render_slot(@inner_block)}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
"""
|
"""
|
||||||
|
|
@ -168,11 +168,11 @@ defmodule PlausibleWeb.Components.Billing do
|
||||||
~H"""
|
~H"""
|
||||||
<tr {@rest}>
|
<tr {@rest}>
|
||||||
<td class={["text-sm py-4 pr-1 sm:whitespace-nowrap text-left", @pad && "pl-6"]}>
|
<td class={["text-sm py-4 pr-1 sm:whitespace-nowrap text-left", @pad && "pl-6"]}>
|
||||||
<%= @title %>
|
{@title}
|
||||||
</td>
|
</td>
|
||||||
<td class="text-sm py-4 sm:whitespace-nowrap text-right">
|
<td class="text-sm py-4 sm:whitespace-nowrap text-right">
|
||||||
<%= Cldr.Number.to_string!(@usage) %>
|
{Cldr.Number.to_string!(@usage)}
|
||||||
<%= if is_number(@limit), do: "/ #{Cldr.Number.to_string!(@limit)}" %>
|
{if is_number(@limit), do: "/ #{Cldr.Number.to_string!(@limit)}"}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
"""
|
"""
|
||||||
|
|
@ -186,7 +186,7 @@ defmodule PlausibleWeb.Components.Billing do
|
||||||
>
|
>
|
||||||
<h4 class="font-black dark:text-gray-100">Monthly quota</h4>
|
<h4 class="font-black dark:text-gray-100">Monthly quota</h4>
|
||||||
<div class="py-2 text-xl font-medium dark:text-gray-100">
|
<div class="py-2 text-xl font-medium dark:text-gray-100">
|
||||||
<%= PlausibleWeb.AuthView.subscription_quota(@subscription, format: :long) %>
|
{PlausibleWeb.AuthView.subscription_quota(@subscription, format: :long)}
|
||||||
</div>
|
</div>
|
||||||
<.styled_link
|
<.styled_link
|
||||||
:if={
|
:if={
|
||||||
|
|
@ -196,7 +196,7 @@ defmodule PlausibleWeb.Components.Billing do
|
||||||
id="#upgrade-or-change-plan-link"
|
id="#upgrade-or-change-plan-link"
|
||||||
href={Routes.billing_path(PlausibleWeb.Endpoint, :choose_plan)}
|
href={Routes.billing_path(PlausibleWeb.Endpoint, :choose_plan)}
|
||||||
>
|
>
|
||||||
<%= change_plan_or_upgrade_text(@subscription) %>
|
{change_plan_or_upgrade_text(@subscription)}
|
||||||
</.styled_link>
|
</.styled_link>
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
|
|
@ -206,13 +206,13 @@ defmodule PlausibleWeb.Components.Billing do
|
||||||
~H"""
|
~H"""
|
||||||
<ul class="w-full py-4">
|
<ul class="w-full py-4">
|
||||||
<li>
|
<li>
|
||||||
Up to <b><%= present_limit(@plan, :monthly_pageview_limit) %></b> monthly pageviews
|
Up to <b>{present_limit(@plan, :monthly_pageview_limit)}</b> monthly pageviews
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
Up to <b><%= present_limit(@plan, :site_limit) %></b> sites
|
Up to <b>{present_limit(@plan, :site_limit)}</b> sites
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
Up to <b><%= present_limit(@plan, :hourly_api_request_limit) %></b> hourly api requests
|
Up to <b>{present_limit(@plan, :hourly_api_request_limit)}</b> hourly api requests
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
"""
|
"""
|
||||||
|
|
@ -258,7 +258,7 @@ defmodule PlausibleWeb.Components.Billing do
|
||||||
@checkout_disabled && "pointer-events-none bg-gray-400 dark:bg-gray-600"
|
@checkout_disabled && "pointer-events-none bg-gray-400 dark:bg-gray-600"
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<%= render_slot(@inner_block) %>
|
{render_slot(@inner_block)}
|
||||||
</button>
|
</button>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ defmodule PlausibleWeb.Components.Billing.Notice do
|
||||||
title="Notice"
|
title="Notice"
|
||||||
{@rest}
|
{@rest}
|
||||||
>
|
>
|
||||||
<%= account_label(@current_user, @billable_user) %> does not have access to <%= @feature_mod.display_name() %>. To get access to this feature,
|
{account_label(@current_user, @billable_user)} does not have access to {@feature_mod.display_name()}. To get access to this feature,
|
||||||
<.upgrade_call_to_action
|
<.upgrade_call_to_action
|
||||||
current_team={@current_team}
|
current_team={@current_team}
|
||||||
current_user={@current_user}
|
current_user={@current_user}
|
||||||
|
|
@ -96,7 +96,7 @@ defmodule PlausibleWeb.Components.Billing.Notice do
|
||||||
def limit_exceeded(assigns) do
|
def limit_exceeded(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<.notice {@rest} title="Notice">
|
<.notice {@rest} title="Notice">
|
||||||
<%= account_label(@current_user, @billable_user) %> is limited to <%= @limit %> <%= @resource %>. To increase this limit,
|
{account_label(@current_user, @billable_user)} is limited to {@limit} {@resource}. To increase this limit,
|
||||||
<.upgrade_call_to_action
|
<.upgrade_call_to_action
|
||||||
current_team={@current_team}
|
current_team={@current_team}
|
||||||
current_user={@current_user}
|
current_user={@current_user}
|
||||||
|
|
@ -239,7 +239,7 @@ defmodule PlausibleWeb.Components.Billing.Notice do
|
||||||
~H"""
|
~H"""
|
||||||
<aside class={@class}>
|
<aside class={@class}>
|
||||||
<.notice title="Pending ownership transfers" class="shadow-md dark:shadow-none mt-4">
|
<.notice title="Pending ownership transfers" class="shadow-md dark:shadow-none mt-4">
|
||||||
<%= @message %> To exclude pending sites from your usage, please go to
|
{@message} To exclude pending sites from your usage, please go to
|
||||||
<.link href="https://plausible.io/sites" class="whitespace-nowrap font-semibold">
|
<.link href="https://plausible.io/sites" class="whitespace-nowrap font-semibold">
|
||||||
plausible.io/sites
|
plausible.io/sites
|
||||||
</.link>
|
</.link>
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ defmodule PlausibleWeb.Components.Billing.PageviewSlider do
|
||||||
<output class="lg:w-1/4 lg:order-1 font-medium text-lg text-gray-600 dark:text-gray-200">
|
<output class="lg:w-1/4 lg:order-1 font-medium text-lg text-gray-600 dark:text-gray-200">
|
||||||
<span :if={@volume != :enterprise}>Up to</span>
|
<span :if={@volume != :enterprise}>Up to</span>
|
||||||
<strong id="slider-value" class="text-gray-900 dark:text-gray-100">
|
<strong id="slider-value" class="text-gray-900 dark:text-gray-100">
|
||||||
<%= format_volume(@volume, @available_volumes) %>
|
{format_volume(@volume, @available_volumes)}
|
||||||
</strong>
|
</strong>
|
||||||
monthly pageviews
|
monthly pageviews
|
||||||
</output>
|
</output>
|
||||||
|
|
@ -39,7 +39,7 @@ defmodule PlausibleWeb.Components.Billing.PageviewSlider do
|
||||||
<form class="max-w-md lg:max-w-none w-full lg:w-1/2 lg:order-2">
|
<form class="max-w-md lg:max-w-none w-full lg:w-1/2 lg:order-2">
|
||||||
<div class="flex items-baseline space-x-2">
|
<div class="flex items-baseline space-x-2">
|
||||||
<span class="text-xs font-medium text-gray-600 dark:text-gray-200">
|
<span class="text-xs font-medium text-gray-600 dark:text-gray-200">
|
||||||
<%= List.first(@slider_labels) %>
|
{List.first(@slider_labels)}
|
||||||
</span>
|
</span>
|
||||||
<div class="flex-1 relative">
|
<div class="flex-1 relative">
|
||||||
<input
|
<input
|
||||||
|
|
@ -64,7 +64,7 @@ defmodule PlausibleWeb.Components.Billing.PageviewSlider do
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span class="text-xs font-medium text-gray-600 dark:text-gray-200">
|
<span class="text-xs font-medium text-gray-600 dark:text-gray-200">
|
||||||
<%= List.last(@slider_labels) %>
|
{List.last(@slider_labels)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ defmodule PlausibleWeb.Components.Billing.PlanBenefits do
|
||||||
<ul role="list" class={["mt-8 space-y-3 text-sm leading-6 xl:mt-10", @class]}>
|
<ul role="list" class={["mt-8 space-y-3 text-sm leading-6 xl:mt-10", @class]}>
|
||||||
<li :for={benefit <- @benefits} class="flex gap-x-3">
|
<li :for={benefit <- @benefits} class="flex gap-x-3">
|
||||||
<Heroicons.check class="h-6 w-5 text-indigo-600 dark:text-green-600" />
|
<Heroicons.check class="h-6 w-5 text-indigo-600 dark:text-green-600" />
|
||||||
<%= if is_binary(benefit), do: benefit, else: benefit.(assigns) %>
|
{if is_binary(benefit), do: benefit, else: benefit.(assigns)}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ defmodule PlausibleWeb.Components.Billing.PlanBox do
|
||||||
!@highlight && "text-gray-900 dark:text-gray-100",
|
!@highlight && "text-gray-900 dark:text-gray-100",
|
||||||
@highlight && "text-indigo-600 dark:text-indigo-300"
|
@highlight && "text-indigo-600 dark:text-indigo-300"
|
||||||
]}>
|
]}>
|
||||||
<%= String.capitalize(to_string(@kind)) %>
|
{String.capitalize(to_string(@kind))}
|
||||||
</h3>
|
</h3>
|
||||||
<.pill :if={@highlight} text={@highlight} />
|
<.pill :if={@highlight} text={@highlight} />
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -98,7 +98,7 @@ defmodule PlausibleWeb.Components.Billing.PlanBox do
|
||||||
id="highlight-pill"
|
id="highlight-pill"
|
||||||
class="rounded-full bg-indigo-600/10 px-2.5 py-1 text-xs font-semibold leading-5 text-indigo-600 dark:text-indigo-300 dark:ring-1 dark:ring-indigo-300/50"
|
class="rounded-full bg-indigo-600/10 px-2.5 py-1 text-xs font-semibold leading-5 text-indigo-600 dark:text-indigo-300 dark:ring-1 dark:ring-indigo-300/50"
|
||||||
>
|
>
|
||||||
<%= @text %>
|
{@text}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
|
|
@ -142,7 +142,7 @@ defmodule PlausibleWeb.Components.Billing.PlanBox do
|
||||||
id={"#{@kind}-price-tag-amount"}
|
id={"#{@kind}-price-tag-amount"}
|
||||||
class="text-4xl font-bold tracking-tight text-gray-900 dark:text-gray-100"
|
class="text-4xl font-bold tracking-tight text-gray-900 dark:text-gray-100"
|
||||||
>
|
>
|
||||||
<%= @plan_to_render.monthly_cost |> Plausible.Billing.format_price() %>
|
{@plan_to_render.monthly_cost |> Plausible.Billing.format_price()}
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
id={"#{@kind}-price-tag-interval"}
|
id={"#{@kind}-price-tag-interval"}
|
||||||
|
|
@ -156,13 +156,13 @@ defmodule PlausibleWeb.Components.Billing.PlanBox do
|
||||||
defp price_tag(%{selected_interval: :yearly} = assigns) do
|
defp price_tag(%{selected_interval: :yearly} = assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<span class="text-2xl font-bold w-max tracking-tight line-through text-gray-500 dark:text-gray-600 mr-1">
|
<span class="text-2xl font-bold w-max tracking-tight line-through text-gray-500 dark:text-gray-600 mr-1">
|
||||||
<%= @plan_to_render.monthly_cost |> Money.mult!(12) |> Plausible.Billing.format_price() %>
|
{@plan_to_render.monthly_cost |> Money.mult!(12) |> Plausible.Billing.format_price()}
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
id={"#{@kind}-price-tag-amount"}
|
id={"#{@kind}-price-tag-amount"}
|
||||||
class="text-4xl font-bold tracking-tight text-gray-900 dark:text-gray-100"
|
class="text-4xl font-bold tracking-tight text-gray-900 dark:text-gray-100"
|
||||||
>
|
>
|
||||||
<%= @plan_to_render.yearly_cost |> Plausible.Billing.format_price() %>
|
{@plan_to_render.yearly_cost |> Plausible.Billing.format_price()}
|
||||||
</span>
|
</span>
|
||||||
<span id={"#{@kind}-price-tag-interval"} class="text-sm font-semibold leading-6 text-gray-600">
|
<span id={"#{@kind}-price-tag-interval"} class="text-sm font-semibold leading-6 text-gray-600">
|
||||||
/year
|
/year
|
||||||
|
|
@ -234,13 +234,13 @@ defmodule PlausibleWeb.Components.Billing.PlanBox do
|
||||||
<% end %>
|
<% end %>
|
||||||
<.tooltip :if={@exceeded_plan_limits != [] && @disabled_message}>
|
<.tooltip :if={@exceeded_plan_limits != [] && @disabled_message}>
|
||||||
<div class="pt-2 text-sm w-full flex items-center text-red-700 dark:text-red-500 justify-center">
|
<div class="pt-2 text-sm w-full flex items-center text-red-700 dark:text-red-500 justify-center">
|
||||||
<%= @disabled_message %>
|
{@disabled_message}
|
||||||
<Heroicons.information_circle class="hidden sm:block w-5 h-5 sm:ml-2" />
|
<Heroicons.information_circle class="hidden sm:block w-5 h-5 sm:ml-2" />
|
||||||
</div>
|
</div>
|
||||||
<:tooltip_content>
|
<:tooltip_content>
|
||||||
Your usage exceeds the following limit(s):<br /><br />
|
Your usage exceeds the following limit(s):<br /><br />
|
||||||
<p :for={limit <- @exceeded_plan_limits}>
|
<p :for={limit <- @exceeded_plan_limits}>
|
||||||
<%= Phoenix.Naming.humanize(limit) %><br />
|
{Phoenix.Naming.humanize(limit)}<br />
|
||||||
</p>
|
</p>
|
||||||
</:tooltip_content>
|
</:tooltip_content>
|
||||||
</.tooltip>
|
</.tooltip>
|
||||||
|
|
@ -248,7 +248,7 @@ defmodule PlausibleWeb.Components.Billing.PlanBox do
|
||||||
:if={@disabled_message && @exceeded_plan_limits == []}
|
:if={@disabled_message && @exceeded_plan_limits == []}
|
||||||
class="pt-2 text-sm w-full text-red-700 dark:text-red-500 text-center"
|
class="pt-2 text-sm w-full text-red-700 dark:text-red-500 text-center"
|
||||||
>
|
>
|
||||||
<%= @disabled_message %>
|
{@disabled_message}
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
@ -337,7 +337,7 @@ defmodule PlausibleWeb.Components.Billing.PlanBox do
|
||||||
@checkout_disabled && "pointer-events-none bg-gray-400 dark:bg-gray-600"
|
@checkout_disabled && "pointer-events-none bg-gray-400 dark:bg-gray-600"
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<%= @change_plan_link_text %>
|
{@change_plan_link_text}
|
||||||
</button>
|
</button>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -34,25 +34,25 @@ defmodule PlausibleWeb.Components.FlowProgress do
|
||||||
:if={idx == @current_step_idx}
|
:if={idx == @current_step_idx}
|
||||||
class="w-5 h-5 bg-indigo-600 text-white rounded-full flex items-center justify-center font-semibold"
|
class="w-5 h-5 bg-indigo-600 text-white rounded-full flex items-center justify-center font-semibold"
|
||||||
>
|
>
|
||||||
<%= idx + 1 %>
|
{idx + 1}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
:if={idx > @current_step_idx}
|
:if={idx > @current_step_idx}
|
||||||
class="w-5 h-5 bg-gray-300 text-white dark:bg-gray-800 rounded-full flex items-center justify-center"
|
class="w-5 h-5 bg-gray-300 text-white dark:bg-gray-800 rounded-full flex items-center justify-center"
|
||||||
>
|
>
|
||||||
<%= idx + 1 %>
|
{idx + 1}
|
||||||
</div>
|
</div>
|
||||||
<span :if={idx < @current_step_idx} class="ml-2 text-gray-500">
|
<span :if={idx < @current_step_idx} class="ml-2 text-gray-500">
|
||||||
<%= step %>
|
{step}
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
:if={idx == @current_step_idx}
|
:if={idx == @current_step_idx}
|
||||||
class="ml-2 font-semibold text-black dark:text-gray-300"
|
class="ml-2 font-semibold text-black dark:text-gray-300"
|
||||||
>
|
>
|
||||||
<%= step %>
|
{step}
|
||||||
</span>
|
</span>
|
||||||
<span :if={idx > @current_step_idx} class="ml-2 text-gray-500">
|
<span :if={idx > @current_step_idx} class="ml-2 text-gray-500">
|
||||||
<%= step %>
|
{step}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div :if={idx + 1 != length(@steps)} class="flex-1 h-px bg-gray-300 mx-4 dark:bg-gray-800 ">
|
<div :if={idx + 1 != length(@steps)} class="flex-1 h-px bg-gray-300 mx-4 dark:bg-gray-800 ">
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
]}
|
]}
|
||||||
{@rest}
|
{@rest}
|
||||||
>
|
>
|
||||||
<%= render_slot(@inner_block) %>
|
{render_slot(@inner_block)}
|
||||||
</button>
|
</button>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
@ -84,7 +84,7 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
[]
|
[]
|
||||||
else
|
else
|
||||||
[
|
[
|
||||||
"data-csrf": Phoenix.HTML.Tag.csrf_token_value(assigns.href),
|
"data-csrf": Phoenix.Controller.get_csrf_token(),
|
||||||
"data-method": assigns.method,
|
"data-method": assigns.method,
|
||||||
"data-to": assigns.href
|
"data-to": assigns.href
|
||||||
]
|
]
|
||||||
|
|
@ -126,7 +126,7 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
{@extra}
|
{@extra}
|
||||||
{@rest}
|
{@rest}
|
||||||
>
|
>
|
||||||
<%= render_slot(@inner_block) %>
|
{render_slot(@inner_block)}
|
||||||
</.link>
|
</.link>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
@ -178,11 +178,11 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
</div>
|
</div>
|
||||||
<div class={["w-full", @title && "ml-3"]}>
|
<div class={["w-full", @title && "ml-3"]}>
|
||||||
<h3 :if={@title} class={"font-medium #{@theme.title_text} mb-2"}>
|
<h3 :if={@title} class={"font-medium #{@theme.title_text} mb-2"}>
|
||||||
<%= @title %>
|
{@title}
|
||||||
</h3>
|
</h3>
|
||||||
<div class={"#{@theme.body_text}"}>
|
<div class={"#{@theme.body_text}"}>
|
||||||
<p>
|
<p>
|
||||||
<%= render_slot(@inner_block) %>
|
{render_slot(@inner_block)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -216,7 +216,7 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
class={"text-indigo-600 hover:text-indigo-700 dark:text-indigo-500 dark:hover:text-indigo-600 " <> @class}
|
class={"text-indigo-600 hover:text-indigo-700 dark:text-indigo-500 dark:hover:text-indigo-600 " <> @class}
|
||||||
{@rest}
|
{@rest}
|
||||||
>
|
>
|
||||||
<%= render_slot(@inner_block) %>
|
{render_slot(@inner_block)}
|
||||||
</.unstyled_link>
|
</.unstyled_link>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
@ -241,10 +241,11 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
class="relative inline-block text-left"
|
class="relative inline-block text-left"
|
||||||
>
|
>
|
||||||
<button x-ref="button" x-on:click="toggle()" type="button" class={List.first(@button).class}>
|
<button x-ref="button" x-on:click="toggle()" type="button" class={List.first(@button).class}>
|
||||||
<%= render_slot(List.first(@button)) %>
|
{render_slot(List.first(@button))}
|
||||||
</button>
|
</button>
|
||||||
<div
|
<div
|
||||||
x-show="open"
|
x-show="open"
|
||||||
|
x-cloak
|
||||||
x-transition:enter="transition ease-out duration-100"
|
x-transition:enter="transition ease-out duration-100"
|
||||||
x-transition:enter-start="opacity-0 scale-95"
|
x-transition:enter-start="opacity-0 scale-95"
|
||||||
x-transition:enter-end="opacity-100 scale-100"
|
x-transition:enter-end="opacity-100 scale-100"
|
||||||
|
|
@ -258,7 +259,7 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
@menu_class
|
@menu_class
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<%= render_slot(List.first(@menu)) %>
|
{render_slot(List.first(@menu))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
|
|
@ -293,7 +294,7 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
data-ui-state={@state}
|
data-ui-state={@state}
|
||||||
{@rest}
|
{@rest}
|
||||||
>
|
>
|
||||||
<%= render_slot(@inner_block) %>
|
{render_slot(@inner_block)}
|
||||||
</.unstyled_link>
|
</.unstyled_link>
|
||||||
"""
|
"""
|
||||||
else
|
else
|
||||||
|
|
@ -301,7 +302,7 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
|
|
||||||
~H"""
|
~H"""
|
||||||
<div data-ui-state={@state} class={@class}>
|
<div data-ui-state={@state} class={@class}>
|
||||||
<%= render_slot(@inner_block) %>
|
{render_slot(@inner_block)}
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
@ -327,7 +328,7 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
[]
|
[]
|
||||||
else
|
else
|
||||||
[
|
[
|
||||||
"data-csrf": Phoenix.HTML.Tag.csrf_token_value(assigns.href),
|
"data-csrf": Phoenix.Controller.get_csrf_token(),
|
||||||
"data-method": assigns.method,
|
"data-method": assigns.method,
|
||||||
"data-to": assigns.href
|
"data-to": assigns.href
|
||||||
]
|
]
|
||||||
|
|
@ -350,13 +351,13 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
{@extra}
|
{@extra}
|
||||||
{@rest}
|
{@rest}
|
||||||
>
|
>
|
||||||
<%= render_slot(@inner_block) %>
|
{render_slot(@inner_block)}
|
||||||
<Heroicons.arrow_top_right_on_square class={["opacity-60", @icon_class]} />
|
<Heroicons.arrow_top_right_on_square class={["opacity-60", @icon_class]} />
|
||||||
</.link>
|
</.link>
|
||||||
"""
|
"""
|
||||||
else
|
else
|
||||||
~H"""
|
~H"""
|
||||||
<.link class={@class} href={@href} {@extra} {@rest}><%= render_slot(@inner_block) %></.link>
|
<.link class={@class} href={@href} {@extra} {@rest}>{render_slot(@inner_block)}</.link>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -388,7 +389,7 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
def settings_tiles(assigns) do
|
def settings_tiles(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<div class="text-gray-900 leading-5 dark:text-gray-100">
|
<div class="text-gray-900 leading-5 dark:text-gray-100">
|
||||||
<%= render_slot(@inner_block) %>
|
{render_slot(@inner_block)}
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
@ -406,12 +407,12 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
<div class="shadow bg-white dark:bg-gray-800 rounded-md mb-6">
|
<div class="shadow bg-white dark:bg-gray-800 rounded-md mb-6">
|
||||||
<header class="relative py-4 px-6">
|
<header class="relative py-4 px-6">
|
||||||
<.title>
|
<.title>
|
||||||
<%= render_slot(@title) %>
|
{render_slot(@title)}
|
||||||
|
|
||||||
<.docs_info :if={@docs} slug={@docs} />
|
<.docs_info :if={@docs} slug={@docs} />
|
||||||
</.title>
|
</.title>
|
||||||
<div class="text-sm mt-px text-gray-500 dark:text-gray-400 leading-5">
|
<div class="text-sm mt-px text-gray-500 dark:text-gray-400 leading-5">
|
||||||
<%= render_slot(@subtitle) %>
|
{render_slot(@subtitle)}
|
||||||
</div>
|
</div>
|
||||||
<%= if @feature_mod do %>
|
<%= if @feature_mod do %>
|
||||||
<PlausibleWeb.Components.Site.Feature.toggle
|
<PlausibleWeb.Components.Site.Feature.toggle
|
||||||
|
|
@ -424,7 +425,7 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div class="pb-4 px-6">
|
<div class="pb-4 px-6">
|
||||||
<%= render_slot(@inner_block) %>
|
{render_slot(@inner_block)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
|
|
@ -455,7 +456,7 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
x-transition:leave-start="opacity-100"
|
x-transition:leave-start="opacity-100"
|
||||||
x-transition:leave-end="opacity-0"
|
x-transition:leave-end="opacity-0"
|
||||||
>
|
>
|
||||||
<%= render_slot(List.first(@tooltip_content)) %>
|
{render_slot(List.first(@tooltip_content))}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
x-on:click="sticky = true; hovered = true"
|
x-on:click="sticky = true; hovered = true"
|
||||||
|
|
@ -463,7 +464,7 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
x-on:mouseover="hovered = true"
|
x-on:mouseover="hovered = true"
|
||||||
x-on:mouseout="hovered = false"
|
x-on:mouseout="hovered = false"
|
||||||
>
|
>
|
||||||
<%= render_slot(@inner_block) %>
|
{render_slot(@inner_block)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
|
|
@ -500,7 +501,7 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
~H"""
|
~H"""
|
||||||
<ol class="list-disc space-y-1 ml-4 text-sm">
|
<ol class="list-disc space-y-1 ml-4 text-sm">
|
||||||
<li :for={item <- @item} class="marker:text-indigo-700 dark:marker:text-indigo-700">
|
<li :for={item <- @item} class="marker:text-indigo-700 dark:marker:text-indigo-700">
|
||||||
<%= render_slot(item) %>
|
{render_slot(item)}
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
"""
|
"""
|
||||||
|
|
@ -520,20 +521,20 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
>
|
>
|
||||||
<div class="p-8">
|
<div class="p-8">
|
||||||
<.title :if={@title != []}>
|
<.title :if={@title != []}>
|
||||||
<%= render_slot(@title) %>
|
{render_slot(@title)}
|
||||||
</.title>
|
</.title>
|
||||||
<div></div>
|
<div></div>
|
||||||
|
|
||||||
<div :if={@subtitle != []} class="text-sm mt-4 leading-6">
|
<div :if={@subtitle != []} class="text-sm mt-4 leading-6">
|
||||||
<%= render_slot(@subtitle) %>
|
{render_slot(@subtitle)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div :if={@title != []} class="mt-8">
|
<div :if={@title != []} class="mt-8">
|
||||||
<%= render_slot(@inner_block) %>
|
{render_slot(@inner_block)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div :if={@title == []}>
|
<div :if={@title == []}>
|
||||||
<%= render_slot(@inner_block) %>
|
{render_slot(@inner_block)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
|
@ -541,7 +542,7 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
class="flex flex-col dark:text-gray-200 border-t border-gray-300 dark:border-gray-700"
|
class="flex flex-col dark:text-gray-200 border-t border-gray-300 dark:border-gray-700"
|
||||||
>
|
>
|
||||||
<div class="p-8">
|
<div class="p-8">
|
||||||
<%= render_slot(@footer) %>
|
{render_slot(@footer)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -561,14 +562,14 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
<table :if={not Enum.empty?(@rows)} class={@width} {@rest}>
|
<table :if={not Enum.empty?(@rows)} class={@width} {@rest}>
|
||||||
<thead :if={@thead != []}>
|
<thead :if={@thead != []}>
|
||||||
<tr class="border-b border-gray-200 dark:border-gray-700">
|
<tr class="border-b border-gray-200 dark:border-gray-700">
|
||||||
<%= render_slot(@thead) %>
|
{render_slot(@thead)}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="divide-y divide-gray-200 dark:divide-gray-700">
|
<tbody class="divide-y divide-gray-200 dark:divide-gray-700">
|
||||||
<tr :for={item <- @rows} {if @row_attrs, do: @row_attrs.(item), else: %{}}>
|
<tr :for={item <- @rows} {if @row_attrs, do: @row_attrs.(item), else: %{}}>
|
||||||
<%= render_slot(@tbody, item) %>
|
{render_slot(@tbody, item)}
|
||||||
</tr>
|
</tr>
|
||||||
<%= render_slot(@inner_block) %>
|
{render_slot(@inner_block)}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
"""
|
"""
|
||||||
|
|
@ -605,10 +606,10 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
{@rest}
|
{@rest}
|
||||||
>
|
>
|
||||||
<div :if={@actions} class="flex gap-2">
|
<div :if={@actions} class="flex gap-2">
|
||||||
<%= render_slot(@inner_block) %>
|
{render_slot(@inner_block)}
|
||||||
</div>
|
</div>
|
||||||
<div :if={!@actions}>
|
<div :if={!@actions}>
|
||||||
<%= render_slot(@inner_block) %>
|
{render_slot(@inner_block)}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
"""
|
"""
|
||||||
|
|
@ -630,7 +631,7 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
|
|
||||||
~H"""
|
~H"""
|
||||||
<th scope="col" class={[@hide_on_mobile && "hidden md:table-cell", @class]}>
|
<th scope="col" class={[@hide_on_mobile && "hidden md:table-cell", @class]}>
|
||||||
<%= render_slot(@inner_block) %>
|
{render_slot(@inner_block)}
|
||||||
</th>
|
</th>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
@ -667,7 +668,7 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
else: "text-gray-900 dark:text-gray-100"
|
else: "text-gray-900 dark:text-gray-100"
|
||||||
)
|
)
|
||||||
]}>
|
]}>
|
||||||
<%= render_slot(@inner_block) %>
|
{render_slot(@inner_block)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
|
|
@ -743,7 +744,7 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<%= render_slot(@inner_block) %>
|
{render_slot(@inner_block)}
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
@ -754,7 +755,7 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
def h2(assigns) do
|
def h2(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<h2 class={[@class || "font-semibold leading-6 text-gray-900 dark:text-gray-100"]}>
|
<h2 class={[@class || "font-semibold leading-6 text-gray-900 dark:text-gray-100"]}>
|
||||||
<%= render_slot(@inner_block) %>
|
{render_slot(@inner_block)}
|
||||||
</h2>
|
</h2>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
@ -765,7 +766,7 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
def title(assigns) do
|
def title(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<.h2 class={["text-lg font-medium text-gray-900 dark:text-gray-100 leading-7", @class]}>
|
<.h2 class={["text-lg font-medium text-gray-900 dark:text-gray-100 leading-7", @class]}>
|
||||||
<%= render_slot(@inner_block) %>
|
{render_slot(@inner_block)}
|
||||||
</.h2>
|
</.h2>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -26,12 +26,12 @@ defmodule PlausibleWeb.Components.Site.Feature do
|
||||||
class={@class}
|
class={@class}
|
||||||
>
|
>
|
||||||
<.toggle_submit set_to={@current_setting} disabled?={@disabled?}>
|
<.toggle_submit set_to={@current_setting} disabled?={@disabled?}>
|
||||||
Show <%= @feature_mod.display_name() %> in the Dashboard
|
Show {@feature_mod.display_name()} in the Dashboard
|
||||||
</.toggle_submit>
|
</.toggle_submit>
|
||||||
</.form>
|
</.form>
|
||||||
|
|
||||||
<div :if={@current_setting}>
|
<div :if={@current_setting}>
|
||||||
<%= render_slot(@inner_block) %>
|
{render_slot(@inner_block)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ defmodule PlausibleWeb.Components.TwoFactor do
|
||||||
assigns = assign(assigns, :code, qr_code)
|
assigns = assign(assigns, :code, qr_code)
|
||||||
|
|
||||||
~H"""
|
~H"""
|
||||||
<%= Phoenix.HTML.raw(@code) %>
|
{Phoenix.HTML.raw(@code)}
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -38,25 +38,29 @@ defmodule PlausibleWeb.Components.TwoFactor do
|
||||||
end
|
end
|
||||||
|
|
||||||
assigns = assign(assigns, :input_class, input_class)
|
assigns = assign(assigns, :input_class, input_class)
|
||||||
|
assigns = assign(assigns, :field, assigns[:form][assigns[:field]])
|
||||||
|
|
||||||
~H"""
|
~H"""
|
||||||
<div class={[@class, "flex items-center"]}>
|
<div class={[@class, "flex items-center"]}>
|
||||||
<%= Phoenix.HTML.Form.text_input(@form, @field,
|
<input
|
||||||
autocomplete: "off",
|
type="text"
|
||||||
class: @input_class,
|
name={@field.name}
|
||||||
oninput:
|
value={@field.value}
|
||||||
|
autocomplete="off"
|
||||||
|
class={@input_class}
|
||||||
|
oninput={
|
||||||
if @show_button? do
|
if @show_button? do
|
||||||
"this.value=this.value.replace(/[^0-9]/g, ''); if (this.value.length >= 6) document.getElementById('#{@id}').focus()"
|
"this.value=this.value.replace(/[^0-9]/g, ''); if (this.value.length >= 6) document.getElementById('#{@id}').focus()"
|
||||||
else
|
else
|
||||||
"this.value=this.value.replace(/[^0-9]/g, '');"
|
"this.value=this.value.replace(/[^0-9]/g, '');"
|
||||||
end,
|
end
|
||||||
onclick: "this.select();",
|
}
|
||||||
oninvalid: @show_button? && "document.getElementById('#{@id}').disabled = false",
|
onclick="this.select();"
|
||||||
maxlength: "6",
|
oninvalid={@show_button? && "document.getElementById('#{@id}').disabled = false"}
|
||||||
placeholder: "••••••",
|
maxlength="6"
|
||||||
value: "",
|
placeholder="••••••"
|
||||||
required: "required"
|
required="required"
|
||||||
) %>
|
/>
|
||||||
<.button
|
<.button
|
||||||
:if={@show_button?}
|
:if={@show_button?}
|
||||||
type="submit"
|
type="submit"
|
||||||
|
|
@ -142,19 +146,19 @@ defmodule PlausibleWeb.Components.TwoFactor do
|
||||||
</div>
|
</div>
|
||||||
<div class="sm:flex sm:items-start">
|
<div class="sm:flex sm:items-start">
|
||||||
<div class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-green-100 sm:mx-0 sm:h-10 sm:w-10">
|
<div class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-green-100 sm:mx-0 sm:h-10 sm:w-10">
|
||||||
<%= render_slot(@icon) %>
|
{render_slot(@icon)}
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left text-gray-900 dark:text-gray-100">
|
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left text-gray-900 dark:text-gray-100">
|
||||||
<h3 class="text-lg leading-6 font-medium" id="modal-title">
|
<h3 class="text-lg leading-6 font-medium" id="modal-title">
|
||||||
<%= @title %>
|
{@title}
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<%= render_slot(@inner_block, f) %>
|
{render_slot(@inner_block, f)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-gray-50 dark:bg-gray-850 px-4 py-3 sm:px-9 sm:flex sm:flex-row-reverse">
|
<div class="bg-gray-50 dark:bg-gray-850 px-4 py-3 sm:px-9 sm:flex sm:flex-row-reverse">
|
||||||
<%= render_slot(@buttons) %>
|
{render_slot(@buttons)}
|
||||||
<.button
|
<.button
|
||||||
type="button"
|
type="button"
|
||||||
x-on:click={"#{@state_param} = false"}
|
x-on:click={"#{@state_param} = false"}
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ defmodule PlausibleWeb.AuthController do
|
||||||
flow = params["flow"] || PlausibleWeb.Flows.register()
|
flow = params["flow"] || PlausibleWeb.Flows.register()
|
||||||
|
|
||||||
render(conn, "activate.html",
|
render(conn, "activate.html",
|
||||||
|
error: nil,
|
||||||
has_email_code?: Plausible.Users.has_email_code?(user),
|
has_email_code?: Plausible.Users.has_email_code?(user),
|
||||||
has_any_memberships?: Plausible.Teams.Users.has_sites?(user),
|
has_any_memberships?: Plausible.Teams.Users.has_sites?(user),
|
||||||
form_submit_url: "/activate?flow=#{flow}"
|
form_submit_url: "/activate?flow=#{flow}"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ defmodule PlausibleWeb.Live.ChoosePlan do
|
||||||
LiveView for upgrading to a plan, or changing an existing plan.
|
LiveView for upgrading to a plan, or changing an existing plan.
|
||||||
"""
|
"""
|
||||||
use PlausibleWeb, :live_view
|
use PlausibleWeb, :live_view
|
||||||
use Phoenix.HTML
|
|
||||||
|
|
||||||
require Plausible.Billing.Subscription.Status
|
require Plausible.Billing.Subscription.Status
|
||||||
|
|
||||||
|
|
@ -107,9 +106,9 @@ defmodule PlausibleWeb.Live.ChoosePlan do
|
||||||
<Notice.upgrade_ineligible :if={not Quota.eligible_for_upgrade?(@usage)} />
|
<Notice.upgrade_ineligible :if={not Quota.eligible_for_upgrade?(@usage)} />
|
||||||
<div class="mx-auto max-w-4xl text-center">
|
<div class="mx-auto max-w-4xl text-center">
|
||||||
<p class="text-4xl font-bold tracking-tight lg:text-5xl">
|
<p class="text-4xl font-bold tracking-tight lg:text-5xl">
|
||||||
<%= if @owned_plan,
|
{if @owned_plan,
|
||||||
do: "Change subscription plan",
|
do: "Change subscription plan",
|
||||||
else: "Upgrade your account" %>
|
else: "Upgrade your account"}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-12 flex flex-col gap-8 lg:flex-row items-center lg:items-baseline">
|
<div class="mt-12 flex flex-col gap-8 lg:flex-row items-center lg:items-baseline">
|
||||||
|
|
|
||||||
|
|
@ -253,9 +253,9 @@ defmodule PlausibleWeb.Live.Components.ComboBox do
|
||||||
class="block truncate py-2 px-3"
|
class="block truncate py-2 px-3"
|
||||||
>
|
>
|
||||||
<%= if @creatable do %>
|
<%= if @creatable do %>
|
||||||
Create "<%= @display_value %>"
|
Create "{@display_value}"
|
||||||
<% else %>
|
<% else %>
|
||||||
<%= @display_value %>
|
{@display_value}
|
||||||
<% end %>
|
<% end %>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ defmodule PlausibleWeb.Live.Components.Form do
|
||||||
<.input name="my-input" errors={["oh no!"]} />
|
<.input name="my-input" errors={["oh no!"]} />
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@default_input_class "text-sm dark:bg-gray-900 block pl-3.5 py-2.5 border-gray-300 dark:border-gray-500 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 rounded-md"
|
@default_input_class "text-sm text-gray-900 dark:text-white dark:bg-gray-900 block pl-3.5 py-2.5 border-gray-300 dark:border-gray-500 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 rounded-md"
|
||||||
|
|
||||||
attr(:id, :any, default: nil)
|
attr(:id, :any, default: nil)
|
||||||
attr(:name, :any)
|
attr(:name, :any)
|
||||||
|
|
@ -55,6 +55,8 @@ defmodule PlausibleWeb.Live.Components.Form do
|
||||||
slot(:inner_block)
|
slot(:inner_block)
|
||||||
|
|
||||||
def input(%{field: %Phoenix.HTML.FormField{} = field} = assigns) do
|
def input(%{field: %Phoenix.HTML.FormField{} = field} = assigns) do
|
||||||
|
errors = if Phoenix.Component.used_input?(field), do: field.errors, else: []
|
||||||
|
|
||||||
assigns
|
assigns
|
||||||
|> assign(
|
|> assign(
|
||||||
field: nil,
|
field: nil,
|
||||||
|
|
@ -63,7 +65,7 @@ defmodule PlausibleWeb.Live.Components.Form do
|
||||||
mt?: assigns.mt?,
|
mt?: assigns.mt?,
|
||||||
width: assigns.width
|
width: assigns.width
|
||||||
)
|
)
|
||||||
|> assign(:errors, Enum.map(field.errors, &translate_error(&1)))
|
|> assign(:errors, Enum.map(errors, &translate_error(&1)))
|
||||||
|> assign_new(:name, fn -> if assigns.multiple, do: field.name <> "[]", else: field.name end)
|
|> assign_new(:name, fn -> if assigns.multiple, do: field.name <> "[]", else: field.name end)
|
||||||
|> assign_new(:value, fn -> field.value end)
|
|> assign_new(:value, fn -> field.value end)
|
||||||
|> input()
|
|> input()
|
||||||
|
|
@ -71,27 +73,27 @@ defmodule PlausibleWeb.Live.Components.Form do
|
||||||
|
|
||||||
def input(%{type: "select"} = assigns) do
|
def input(%{type: "select"} = assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<div phx-feedback-for={@name} class={@mt? && "mt-2"}>
|
<div class={@mt? && "mt-2"}>
|
||||||
<.label for={@id} class="mb-2"><%= @label %></.label>
|
<.label for={@id} class="mb-2">{@label}</.label>
|
||||||
|
|
||||||
<p :if={@help_text} class="text-gray-500 dark:text-gray-400 mb-2 text-sm">
|
<p :if={@help_text} class="text-gray-500 dark:text-gray-400 mb-2 text-sm">
|
||||||
<%= @help_text %>
|
{@help_text}
|
||||||
</p>
|
</p>
|
||||||
<select id={@id} name={@name} multiple={@multiple} class={[@class, @width]} {@rest}>
|
<select id={@id} name={@name} multiple={@multiple} class={[@class, @width]} {@rest}>
|
||||||
<option :if={@prompt} value=""><%= @prompt %></option>
|
<option :if={@prompt} value="">{@prompt}</option>
|
||||||
<%= Phoenix.HTML.Form.options_for_select(@options, @value) %>
|
{Phoenix.HTML.Form.options_for_select(@options, @value)}
|
||||||
</select>
|
</select>
|
||||||
<.error :for={msg <- @errors}><%= msg %></.error>
|
<.error :for={msg <- @errors}>{msg}</.error>
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
def input(%{type: "checkbox"} = assigns) do
|
def input(%{type: "checkbox"} = assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<div
|
<div class={[
|
||||||
phx-feedback-for={@name}
|
"flex flex-inline items-center sm:justify-start justify-center gap-x-2",
|
||||||
class={["flex flex-inline items-center sm:justify-start justify-center gap-x-2", @mt? && "mt-2"]}
|
@mt? && "mt-2"
|
||||||
>
|
]}>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
value={@value || "true"}
|
value={@value || "true"}
|
||||||
|
|
@ -99,7 +101,7 @@ defmodule PlausibleWeb.Live.Components.Form do
|
||||||
name={@name}
|
name={@name}
|
||||||
class="block h-5 w-5 rounded dark:bg-gray-700 border-gray-300 text-indigo-600 focus:ring-indigo-600"
|
class="block h-5 w-5 rounded dark:bg-gray-700 border-gray-300 text-indigo-600 focus:ring-indigo-600"
|
||||||
/>
|
/>
|
||||||
<.label for={@id}><%= @label %></.label>
|
<.label for={@id}>{@label}</.label>
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
@ -116,12 +118,12 @@ defmodule PlausibleWeb.Live.Components.Form do
|
||||||
assigns = assign(assigns, :errors, errors)
|
assigns = assign(assigns, :errors, errors)
|
||||||
|
|
||||||
~H"""
|
~H"""
|
||||||
<div phx-feedback-for={@name} class={@mt? && "mt-2"}>
|
<div class={@mt? && "mt-2"}>
|
||||||
<.label :if={@label != nil and @label != ""} for={@id} class="mb-2">
|
<.label :if={@label != nil and @label != ""} for={@id} class="mb-2">
|
||||||
<%= @label %>
|
{@label}
|
||||||
</.label>
|
</.label>
|
||||||
<p :if={@help_text} class="text-gray-500 dark:text-gray-400 mb-2 text-sm">
|
<p :if={@help_text} class="text-gray-500 dark:text-gray-400 mb-2 text-sm">
|
||||||
<%= @help_text %>
|
{@help_text}
|
||||||
</p>
|
</p>
|
||||||
<input
|
<input
|
||||||
type={@type}
|
type={@type}
|
||||||
|
|
@ -131,9 +133,9 @@ defmodule PlausibleWeb.Live.Components.Form do
|
||||||
class={[@class, @width, assigns[:rest][:disabled] && "text-gray-500 dark:text-gray-400"]}
|
class={[@class, @width, assigns[:rest][:disabled] && "text-gray-500 dark:text-gray-400"]}
|
||||||
{@rest}
|
{@rest}
|
||||||
/>
|
/>
|
||||||
<%= render_slot(@inner_block) %>
|
{render_slot(@inner_block)}
|
||||||
<.error :for={msg <- @errors}>
|
<.error :for={msg <- @errors}>
|
||||||
<%= msg %>
|
{msg}
|
||||||
</.error>
|
</.error>
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
|
|
@ -153,7 +155,7 @@ defmodule PlausibleWeb.Live.Components.Form do
|
||||||
<div>
|
<div>
|
||||||
<div :if={@label}>
|
<div :if={@label}>
|
||||||
<.label for={@id} class="mb-2">
|
<.label for={@id} class="mb-2">
|
||||||
<%= @label %>
|
{@label}
|
||||||
</.label>
|
</.label>
|
||||||
</div>
|
</div>
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
|
|
@ -218,10 +220,14 @@ defmodule PlausibleWeb.Live.Components.Form do
|
||||||
|> assign(:too_weak?, too_weak?)
|
|> assign(:too_weak?, too_weak?)
|
||||||
|> assign(:field, %{field | errors: errors})
|
|> assign(:field, %{field | errors: errors})
|
||||||
|> assign(:strength, strength)
|
|> assign(:strength, strength)
|
||||||
|
|> assign(
|
||||||
|
:show_meter?,
|
||||||
|
Phoenix.Component.used_input?(field) && (too_weak? || strength.score > 0)
|
||||||
|
)
|
||||||
|
|
||||||
~H"""
|
~H"""
|
||||||
<.input field={@field} type="password" autocomplete="new-password" label={@label} id={@id} {@rest}>
|
<.input field={@field} type="password" autocomplete="new-password" label={@label} id={@id} {@rest}>
|
||||||
<.strength_meter :if={@too_weak? or @strength.score > 0} {@strength} />
|
<.strength_meter :if={@show_meter?} {@strength} />
|
||||||
</.input>
|
</.input>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
@ -256,7 +262,7 @@ defmodule PlausibleWeb.Live.Components.Form do
|
||||||
assigns = assign(assigns, :class, final_class)
|
assigns = assign(assigns, :class, final_class)
|
||||||
|
|
||||||
~H"""
|
~H"""
|
||||||
<p class={@class}>Min <%= @minimum %> characters</p>
|
<p class={@class}>Min {@minimum} characters</p>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -311,11 +317,11 @@ defmodule PlausibleWeb.Live.Components.Form do
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p :if={@score <= 2} class="text-sm text-red-500 phx-no-feedback:hidden">
|
<p :if={@score <= 2} class="text-sm text-red-500">
|
||||||
Password is too weak
|
Password is too weak
|
||||||
</p>
|
</p>
|
||||||
<p :if={@feedback} class="text-xs text-gray-500">
|
<p :if={@feedback} class="text-xs text-gray-500">
|
||||||
<%= @feedback %>
|
{@feedback}
|
||||||
</p>
|
</p>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
@ -330,7 +336,7 @@ defmodule PlausibleWeb.Live.Components.Form do
|
||||||
def label(assigns) do
|
def label(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<label for={@for} class={["text-sm block font-medium dark:text-gray-100", @class]}>
|
<label for={@for} class={["text-sm block font-medium dark:text-gray-100", @class]}>
|
||||||
<%= render_slot(@inner_block) %>
|
{render_slot(@inner_block)}
|
||||||
</label>
|
</label>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
@ -342,8 +348,8 @@ defmodule PlausibleWeb.Live.Components.Form do
|
||||||
|
|
||||||
def error(assigns) do
|
def error(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<p class="flex gap-3 text-sm leading-6 text-red-500 phx-no-feedback:hidden">
|
<p class="flex gap-3 text-sm leading-6 text-red-500">
|
||||||
<%= render_slot(@inner_block) %>
|
{render_slot(@inner_block)}
|
||||||
</p>
|
</p>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -260,7 +260,7 @@ defmodule PlausibleWeb.Live.Components.Modal do
|
||||||
x-transition:leave-end="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
x-transition:leave-end="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||||
x-on:click.outside="closeModal()"
|
x-on:click.outside="closeModal()"
|
||||||
>
|
>
|
||||||
<%= render_slot(@inner_block, modal_unique_id(@modal_sequence_id)) %>
|
{render_slot(@inner_block, modal_unique_id(@modal_sequence_id))}
|
||||||
</Phoenix.Component.focus_wrap>
|
</Phoenix.Component.focus_wrap>
|
||||||
<div x-show="modalOpen" class="modal-loading hidden w-full self-center">
|
<div x-show="modalOpen" class="modal-loading hidden w-full self-center">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ defmodule PlausibleWeb.Live.Components.Pagination do
|
||||||
>
|
>
|
||||||
<div class="hidden sm:block">
|
<div class="hidden sm:block">
|
||||||
<p class="text-sm text-gray-700 dark:text-gray-300">
|
<p class="text-sm text-gray-700 dark:text-gray-300">
|
||||||
<%= render_slot(@inner_block) %>
|
{render_slot(@inner_block)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-1 flex justify-between sm:justify-end">
|
<div class="flex-1 flex justify-between sm:justify-end">
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ defmodule PlausibleWeb.Live.Components.Verification do
|
||||||
<span :if={not @finished?}>Verifying your installation</span>
|
<span :if={not @finished?}>Verifying your installation</span>
|
||||||
|
|
||||||
<span :if={@finished? and not @success? and @interpretation}>
|
<span :if={@finished? and not @success? and @interpretation}>
|
||||||
<%= List.first(@interpretation.errors) %>
|
{List.first(@interpretation.errors)}
|
||||||
</span>
|
</span>
|
||||||
</.title>
|
</.title>
|
||||||
<p :if={@finished? and @success?} id="progress" class="text-sm mt-4">
|
<p :if={@finished? and @success?} id="progress" class="text-sm mt-4">
|
||||||
|
|
@ -67,19 +67,19 @@ defmodule PlausibleWeb.Live.Components.Verification do
|
||||||
</p>
|
</p>
|
||||||
<p
|
<p
|
||||||
:if={@finished? and @success? and @awaiting_first_pageview?}
|
:if={@finished? and @success? and @awaiting_first_pageview?}
|
||||||
id="progress"
|
id="awaiting"
|
||||||
class="text-sm mt-4 animate-pulse"
|
class="text-sm mt-4 animate-pulse"
|
||||||
>
|
>
|
||||||
Awaiting your first pageview
|
Awaiting your first pageview
|
||||||
</p>
|
</p>
|
||||||
<p :if={not @finished?} class="text-sm mt-4 animate-pulse" id="progress"><%= @message %></p>
|
<p :if={not @finished?} class="text-sm mt-4 animate-pulse" id="progress">{@message}</p>
|
||||||
|
|
||||||
<p
|
<p
|
||||||
:if={@finished? and not @success? and @interpretation}
|
:if={@finished? and not @success? and @interpretation}
|
||||||
class="mt-4 text-sm text-ellipsis overflow-hidden"
|
class="mt-4 text-sm text-ellipsis overflow-hidden"
|
||||||
id="recommendation"
|
id="recommendation"
|
||||||
>
|
>
|
||||||
<span><%= List.first(@interpretation.recommendations).text %>. </span>
|
<span>{List.first(@interpretation.recommendations).text}. </span>
|
||||||
<.styled_link href={List.first(@interpretation.recommendations).url} new_tab={true}>
|
<.styled_link href={List.first(@interpretation.recommendations).url} new_tab={true}>
|
||||||
Learn more
|
Learn more
|
||||||
</.styled_link>
|
</.styled_link>
|
||||||
|
|
@ -145,7 +145,7 @@ defmodule PlausibleWeb.Live.Components.Verification do
|
||||||
<.focus_list>
|
<.focus_list>
|
||||||
<:item :for={{diag, value} <- Map.from_struct(@verification_state.diagnostics)}>
|
<:item :for={{diag, value} <- Map.from_struct(@verification_state.diagnostics)}>
|
||||||
<span class="text-sm">
|
<span class="text-sm">
|
||||||
<%= Phoenix.Naming.humanize(diag) %>: <span class="font-mono"><%= value %></span>
|
{Phoenix.Naming.humanize(diag)}: <span class="font-mono">{value}</span>
|
||||||
</span>
|
</span>
|
||||||
</:item>
|
</:item>
|
||||||
</.focus_list>
|
</.focus_list>
|
||||||
|
|
|
||||||
|
|
@ -173,7 +173,7 @@ defmodule PlausibleWeb.Live.CSVExport do
|
||||||
<:tbody :let={export}>
|
<:tbody :let={export}>
|
||||||
<.td>
|
<.td>
|
||||||
<.styled_link href={@href}>
|
<.styled_link href={@href}>
|
||||||
<%= export.name %>
|
{export.name}
|
||||||
</.styled_link>
|
</.styled_link>
|
||||||
</.td>
|
</.td>
|
||||||
<.td actions>
|
<.td actions>
|
||||||
|
|
@ -188,14 +188,14 @@ defmodule PlausibleWeb.Live.CSVExport do
|
||||||
<p :if={@export.expires_at} class="text-sm">
|
<p :if={@export.expires_at} class="text-sm">
|
||||||
Note: this file will expire
|
Note: this file will expire
|
||||||
<.hint message={@export.expires_at}>
|
<.hint message={@export.expires_at}>
|
||||||
<%= Timex.Format.DateTime.Formatters.Relative.format!(@export.expires_at, "{relative}") %>.
|
{Timex.Format.DateTime.Formatters.Relative.format!(@export.expires_at, "{relative}")}.
|
||||||
</.hint>
|
</.hint>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p :if={@storage == "local"} class="text-sm">
|
<p :if={@storage == "local"} class="text-sm">
|
||||||
Located at
|
Located at
|
||||||
<.hint message={@export.path}><%= format_path(@export.path) %></.hint>
|
<.hint message={@export.path}>{format_path(@export.path)}</.hint>
|
||||||
(<%= format_bytes(@export.size) %>)
|
({format_bytes(@export.size)})
|
||||||
</p>
|
</p>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
@ -203,7 +203,7 @@ defmodule PlausibleWeb.Live.CSVExport do
|
||||||
defp hint(assigns) do
|
defp hint(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<span title={@message} class="underline cursor-help underline-offset-2 decoration-dashed">
|
<span title={@message} class="underline cursor-help underline-offset-2 decoration-dashed">
|
||||||
<%= render_slot(@inner_block) %>
|
{render_slot(@inner_block)}
|
||||||
</span>
|
</span>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ defmodule PlausibleWeb.Live.CSVImport do
|
||||||
original={@original_date_range}
|
original={@original_date_range}
|
||||||
/>
|
/>
|
||||||
<p :for={error <- upload_errors(@uploads.import)} class="text-red-400">
|
<p :for={error <- upload_errors(@uploads.import)} class="text-red-400">
|
||||||
<%= error_to_string(error) %>
|
{error_to_string(error)}
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -151,8 +151,8 @@ defmodule PlausibleWeb.Live.CSVImport do
|
||||||
defp dates(assigns) do
|
defp dates(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<span class="whitespace-nowrap">
|
<span class="whitespace-nowrap">
|
||||||
<span class="font-medium"><%= @range.first %></span>
|
<span class="font-medium">{@range.first}</span>
|
||||||
to <span class="font-medium"><%= @range.last %></span>
|
to <span class="font-medium">{@range.last}</span>
|
||||||
</span>
|
</span>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
@ -182,15 +182,15 @@ defmodule PlausibleWeb.Live.CSVImport do
|
||||||
if(@status == :error, do: "text-red-600 dark:text-red-700")
|
if(@status == :error, do: "text-red-600 dark:text-red-700")
|
||||||
]}>
|
]}>
|
||||||
<%= if @upload do %>
|
<%= if @upload do %>
|
||||||
<%= @upload.client_name %>
|
{@upload.client_name}
|
||||||
<% else %>
|
<% else %>
|
||||||
<%= @table %>_YYYYMMDD_YYYYMMDD.csv
|
{@table}_YYYYMMDD_YYYYMMDD.csv
|
||||||
<% end %>
|
<% end %>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p :for={error <- @errors} class="ml-6 text-sm text-red-600 dark:text-red-700">
|
<p :for={error <- @errors} class="ml-6 text-sm text-red-600 dark:text-red-700">
|
||||||
<%= error_to_string(error) %>
|
{error_to_string(error)}
|
||||||
</p>
|
</p>
|
||||||
</li>
|
</li>
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -55,10 +55,10 @@ defmodule PlausibleWeb.Live.Flash do
|
||||||
<.icon_success />
|
<.icon_success />
|
||||||
</:icon>
|
</:icon>
|
||||||
<:title>
|
<:title>
|
||||||
<%= Flash.get(@flash, :success_title) || "Success!" %>
|
{Flash.get(@flash, :success_title) || "Success!"}
|
||||||
</:title>
|
</:title>
|
||||||
<:message>
|
<:message>
|
||||||
<%= Flash.get(@flash, :success) %>
|
{Flash.get(@flash, :success)}
|
||||||
</:message>
|
</:message>
|
||||||
</.flash>
|
</.flash>
|
||||||
<.flash :if={Flash.get(@flash, :error)} key="error">
|
<.flash :if={Flash.get(@flash, :error)} key="error">
|
||||||
|
|
@ -66,10 +66,10 @@ defmodule PlausibleWeb.Live.Flash do
|
||||||
<.icon_error />
|
<.icon_error />
|
||||||
</:icon>
|
</:icon>
|
||||||
<:title>
|
<:title>
|
||||||
<%= Flash.get(@flash, :error_title) || "Error!" %>
|
{Flash.get(@flash, :error_title) || "Error!"}
|
||||||
</:title>
|
</:title>
|
||||||
<:message>
|
<:message>
|
||||||
<%= Flash.get(@flash, :error) %>
|
{Flash.get(@flash, :error)}
|
||||||
</:message>
|
</:message>
|
||||||
</.flash>
|
</.flash>
|
||||||
<.flash
|
<.flash
|
||||||
|
|
@ -96,7 +96,7 @@ defmodule PlausibleWeb.Live.Flash do
|
||||||
end
|
end
|
||||||
|
|
||||||
slot(:icon, required: true)
|
slot(:icon, required: true)
|
||||||
slot(:title, require: true)
|
slot(:title, required: true)
|
||||||
slot(:message, required: true)
|
slot(:message, required: true)
|
||||||
attr(:key, :string, default: nil)
|
attr(:key, :string, default: nil)
|
||||||
attr(:on_close, :any, default: "lv:clear-flash")
|
attr(:on_close, :any, default: "lv:clear-flash")
|
||||||
|
|
@ -115,13 +115,13 @@ defmodule PlausibleWeb.Live.Flash do
|
||||||
<div class="rounded-lg ring-1 ring-black ring-opacity-5 overflow-hidden">
|
<div class="rounded-lg ring-1 ring-black ring-opacity-5 overflow-hidden">
|
||||||
<div class="p-4">
|
<div class="p-4">
|
||||||
<div class="flex items-start">
|
<div class="flex items-start">
|
||||||
<%= render_slot(@icon) %>
|
{render_slot(@icon)}
|
||||||
<div class="ml-3 w-0 flex-1 pt-0.5">
|
<div class="ml-3 w-0 flex-1 pt-0.5">
|
||||||
<p class="text-sm leading-5 font-medium text-gray-900 dark:text-gray-100">
|
<p class="text-sm leading-5 font-medium text-gray-900 dark:text-gray-100">
|
||||||
<%= render_slot(@title) %>
|
{render_slot(@title)}
|
||||||
</p>
|
</p>
|
||||||
<p class="mt-1 text-sm leading-5 text-gray-500 dark:text-gray-200">
|
<p class="mt-1 text-sm leading-5 text-gray-500 dark:text-gray-200">
|
||||||
<%= render_slot(@message) %>
|
{render_slot(@message)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-4 flex-shrink-0 flex">
|
<div class="ml-4 flex-shrink-0 flex">
|
||||||
|
|
|
||||||
|
|
@ -56,8 +56,8 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
|
||||||
def render(assigns) do
|
def render(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<div id={@id}>
|
<div id={@id}>
|
||||||
<%= if @goal, do: edit_form(assigns) %>
|
{if @goal, do: edit_form(assigns)}
|
||||||
<%= if is_nil(@goal), do: create_form(assigns) %>
|
{if is_nil(@goal), do: create_form(assigns)}
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
@ -65,7 +65,7 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
|
||||||
def edit_form(assigns) do
|
def edit_form(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<.form :let={f} for={@form} phx-submit="save-goal" phx-target={@myself}>
|
<.form :let={f} for={@form} phx-submit="save-goal" phx-target={@myself}>
|
||||||
<.title>Edit Goal for <%= @domain %></.title>
|
<.title>Edit Goal for {@domain}</.title>
|
||||||
|
|
||||||
<.custom_event_fields
|
<.custom_event_fields
|
||||||
:if={@selected_tab == "custom_events"}
|
:if={@selected_tab == "custom_events"}
|
||||||
|
|
@ -105,7 +105,7 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
|
||||||
>
|
>
|
||||||
<.spinner class="spinner block absolute right-9 top-8" x-show="tabSelectionInProgress" />
|
<.spinner class="spinner block absolute right-9 top-8" x-show="tabSelectionInProgress" />
|
||||||
|
|
||||||
<.title>Add Goal for <%= @domain %></.title>
|
<.title>Add Goal for {@domain}</.title>
|
||||||
|
|
||||||
<.tabs selected_tab={@selected_tab} myself={@myself} />
|
<.tabs selected_tab={@selected_tab} myself={@myself} />
|
||||||
|
|
||||||
|
|
@ -145,7 +145,7 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
|
||||||
phx-target={@myself}
|
phx-target={@myself}
|
||||||
>
|
>
|
||||||
<span :if={@event_name_options_count > 1}>
|
<span :if={@event_name_options_count > 1}>
|
||||||
Already sending custom events? We've found <%= @event_name_options_count %> custom events from the last 6 months that are not yet configured as goals. Click here to add them.
|
Already sending custom events? We've found {@event_name_options_count} custom events from the last 6 months that are not yet configured as goals. Click here to add them.
|
||||||
</span>
|
</span>
|
||||||
<span :if={@event_name_options_count == 1}>
|
<span :if={@event_name_options_count == 1}>
|
||||||
Already sending custom events? We've found 1 custom event from the last 6 months that is not yet configured as a goal. Click here to add it.
|
Already sending custom events? We've found 1 custom event from the last 6 months that is not yet configured as a goal. Click here to add it.
|
||||||
|
|
@ -182,7 +182,7 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<.error :for={msg <- Enum.map(@f[:page_path].errors, &translate_error/1)}>
|
<.error :for={msg <- Enum.map(@f[:page_path].errors, &translate_error/1)}>
|
||||||
<%= msg %>
|
{msg}
|
||||||
</.error>
|
</.error>
|
||||||
|
|
||||||
<.input
|
<.input
|
||||||
|
|
@ -241,7 +241,7 @@ defmodule PlausibleWeb.Live.GoalSettings.Form do
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<.error :for={msg <- Enum.map(@f[:event_name].errors, &translate_error/1)}>
|
<.error :for={msg <- Enum.map(@f[:event_name].errors, &translate_error/1)}>
|
||||||
<%= msg %>
|
{msg}
|
||||||
</.error>
|
</.error>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ defmodule PlausibleWeb.Live.GoalSettings.List do
|
||||||
<div class="truncate block">
|
<div class="truncate block">
|
||||||
<%= if not @revenue_goals_enabled? && goal.currency do %>
|
<%= if not @revenue_goals_enabled? && goal.currency do %>
|
||||||
<div class="truncate">
|
<div class="truncate">
|
||||||
<%= goal %>
|
{goal}
|
||||||
<br />
|
<br />
|
||||||
<span class="text-red-600">
|
<span class="text-red-600">
|
||||||
Unlock Revenue Goals by upgrading to a business plan
|
Unlock Revenue Goals by upgrading to a business plan
|
||||||
|
|
@ -44,7 +44,7 @@ defmodule PlausibleWeb.Live.GoalSettings.List do
|
||||||
</div>
|
</div>
|
||||||
<% else %>
|
<% else %>
|
||||||
<.goal_description goal={goal} />
|
<.goal_description goal={goal} />
|
||||||
<span><%= goal %></span>
|
<span>{goal}</span>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -115,11 +115,11 @@ defmodule PlausibleWeb.Live.GoalSettings.List do
|
||||||
def goal_description(assigns) do
|
def goal_description(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<span :if={@goal.page_path} class="block truncate text-gray-400 dark:text-gray-600">
|
<span :if={@goal.page_path} class="block truncate text-gray-400 dark:text-gray-600">
|
||||||
<%= pageview_description(@goal) %>
|
{pageview_description(@goal)}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span :if={@goal.event_name} class="block truncate text-gray-400 dark:text-gray-600">
|
<span :if={@goal.event_name} class="block truncate text-gray-400 dark:text-gray-600">
|
||||||
<%= custom_event_description(@goal) %>
|
{custom_event_description(@goal)}
|
||||||
</span>
|
</span>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ defmodule PlausibleWeb.Live.ImportsExportsSettings do
|
||||||
|
|
||||||
~H"""
|
~H"""
|
||||||
<.notice :if={@import_warning} theme={:gray}>
|
<.notice :if={@import_warning} theme={:gray}>
|
||||||
<%= @import_warning %>
|
{@import_warning}
|
||||||
</.notice>
|
</.notice>
|
||||||
|
|
||||||
<div class="mt-4 flex justify-end gap-x-4">
|
<div class="mt-4 flex justify-end gap-x-4">
|
||||||
|
|
@ -132,24 +132,22 @@ defmodule PlausibleWeb.Live.ImportsExportsSettings do
|
||||||
class="max-w-sm"
|
class="max-w-sm"
|
||||||
title={"#{Plausible.Imported.SiteImport.label(entry.site_import)} created at #{format_date(entry.site_import.inserted_at)}"}
|
title={"#{Plausible.Imported.SiteImport.label(entry.site_import)} created at #{format_date(entry.site_import.inserted_at)}"}
|
||||||
>
|
>
|
||||||
<%= Plausible.Imported.SiteImport.label(entry.site_import) %>
|
{Plausible.Imported.SiteImport.label(entry.site_import)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</.td>
|
</.td>
|
||||||
|
|
||||||
<.td hide_on_mobile>
|
<.td hide_on_mobile>
|
||||||
<%= format_date(entry.site_import.start_date) %> - <%= format_date(
|
{format_date(entry.site_import.start_date)} - {format_date(entry.site_import.end_date)}
|
||||||
entry.site_import.end_date
|
|
||||||
) %>
|
|
||||||
</.td>
|
</.td>
|
||||||
|
|
||||||
<.td>
|
<.td>
|
||||||
<div class="text-right">
|
<div class="text-right">
|
||||||
<%= if entry.live_status == SiteImport.completed(),
|
{if entry.live_status == SiteImport.completed(),
|
||||||
do:
|
do:
|
||||||
PlausibleWeb.StatsView.large_number_format(
|
PlausibleWeb.StatsView.large_number_format(
|
||||||
pageview_count(entry.site_import, @pageview_counts)
|
pageview_count(entry.site_import, @pageview_counts)
|
||||||
) %>
|
)}
|
||||||
</div>
|
</div>
|
||||||
</.td>
|
</.td>
|
||||||
<.td actions>
|
<.td actions>
|
||||||
|
|
|
||||||
|
|
@ -293,12 +293,12 @@ defmodule PlausibleWeb.Live.Installation do
|
||||||
class="block h-5 w-5 rounded dark:bg-gray-700 border-gray-300 text-indigo-600 focus:ring-indigo-600 mr-2"
|
class="block h-5 w-5 rounded dark:bg-gray-700 border-gray-300 text-indigo-600 focus:ring-indigo-600 mr-2"
|
||||||
/>
|
/>
|
||||||
<label for={"check-#{@variant}"}>
|
<label for={"check-#{@variant}"}>
|
||||||
<%= @label %>
|
{@label}
|
||||||
</label>
|
</label>
|
||||||
<div class="ml-2 collapse md:visible">
|
<div class="ml-2 collapse md:visible">
|
||||||
<.tooltip sticky?={false}>
|
<.tooltip sticky?={false}>
|
||||||
<:tooltip_content>
|
<:tooltip_content>
|
||||||
<%= @tooltip %>
|
{@tooltip}
|
||||||
<br /><br />Click to learn more.
|
<br /><br />Click to learn more.
|
||||||
</:tooltip_content>
|
</:tooltip_content>
|
||||||
<a href={@learn_more} target="_blank" rel="noopener noreferrer">
|
<a href={@learn_more} target="_blank" rel="noopener noreferrer">
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ defmodule PlausibleWeb.Live.Plugins.API.Settings do
|
||||||
<.flash_messages flash={@flash} />
|
<.flash_messages flash={@flash} />
|
||||||
|
|
||||||
<%= if @add_token? do %>
|
<%= if @add_token? do %>
|
||||||
<%= live_render(
|
{live_render(
|
||||||
@socket,
|
@socket,
|
||||||
PlausibleWeb.Live.Plugins.API.TokenForm,
|
PlausibleWeb.Live.Plugins.API.TokenForm,
|
||||||
id: "token-form",
|
id: "token-form",
|
||||||
|
|
@ -44,7 +44,7 @@ defmodule PlausibleWeb.Live.Plugins.API.Settings do
|
||||||
"token_description" => @token_description,
|
"token_description" => @token_description,
|
||||||
"rendered_by" => self()
|
"rendered_by" => self()
|
||||||
}
|
}
|
||||||
) %>
|
)}
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -64,14 +64,14 @@ defmodule PlausibleWeb.Live.Plugins.API.Settings do
|
||||||
<:tbody :let={token}>
|
<:tbody :let={token}>
|
||||||
<.td>
|
<.td>
|
||||||
<span class="token-description">
|
<span class="token-description">
|
||||||
<%= token.description %>
|
{token.description}
|
||||||
</span>
|
</span>
|
||||||
</.td>
|
</.td>
|
||||||
<.td hide_on_mobile>
|
<.td hide_on_mobile>
|
||||||
**********<%= token.hint %>
|
**********{token.hint}
|
||||||
</.td>
|
</.td>
|
||||||
<.td hide_on_mobile>
|
<.td hide_on_mobile>
|
||||||
<%= Plausible.Plugins.API.Token.last_used_humanize(token) %>
|
{Plausible.Plugins.API.Token.last_used_humanize(token)}
|
||||||
</.td>
|
</.td>
|
||||||
<.td actions>
|
<.td actions>
|
||||||
<.delete_button
|
<.delete_button
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ defmodule PlausibleWeb.Live.Plugins.API.TokenForm do
|
||||||
phx-click-away="cancel-add-token"
|
phx-click-away="cancel-add-token"
|
||||||
>
|
>
|
||||||
<.title>
|
<.title>
|
||||||
Add Plugin Token for <%= @domain %>
|
Add Plugin Token for {@domain}
|
||||||
</.title>
|
</.title>
|
||||||
|
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ defmodule PlausibleWeb.Live.PropsSettings do
|
||||||
<section id="props-settings-main">
|
<section id="props-settings-main">
|
||||||
<.flash_messages flash={@flash} />
|
<.flash_messages flash={@flash} />
|
||||||
<%= if @add_prop? do %>
|
<%= if @add_prop? do %>
|
||||||
<%= live_render(
|
{live_render(
|
||||||
@socket,
|
@socket,
|
||||||
PlausibleWeb.Live.PropsSettings.Form,
|
PlausibleWeb.Live.PropsSettings.Form,
|
||||||
id: "props-form",
|
id: "props-form",
|
||||||
|
|
@ -48,7 +48,7 @@ defmodule PlausibleWeb.Live.PropsSettings do
|
||||||
"site_id" => @site_id,
|
"site_id" => @site_id,
|
||||||
"rendered_by" => self()
|
"rendered_by" => self()
|
||||||
}
|
}
|
||||||
) %>
|
)}
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<.live_component
|
<.live_component
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ defmodule PlausibleWeb.Live.PropsSettings.Form do
|
||||||
phx-submit="allow-prop"
|
phx-submit="allow-prop"
|
||||||
phx-click-away="cancel-allow-prop"
|
phx-click-away="cancel-allow-prop"
|
||||||
>
|
>
|
||||||
<.title>Add Property for <%= @domain %></.title>
|
<.title>Add Property for {@domain}</.title>
|
||||||
|
|
||||||
<div class="mt-6">
|
<div class="mt-6">
|
||||||
<.label for="prop_input">
|
<.label for="prop_input">
|
||||||
|
|
@ -89,9 +89,9 @@ defmodule PlausibleWeb.Live.PropsSettings.Form do
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<.error :for={{msg, opts} <- f[:allowed_event_props].errors}>
|
<.error :for={{msg, opts} <- f[:allowed_event_props].errors}>
|
||||||
<%= Enum.reduce(opts, msg, fn {key, value}, acc ->
|
{Enum.reduce(opts, msg, fn {key, value}, acc ->
|
||||||
String.replace(acc, "%{#{key}}", fn _ -> to_string(value) end)
|
String.replace(acc, "%{#{key}}", fn _ -> to_string(value) end)
|
||||||
end) %>
|
end)}
|
||||||
</.error>
|
</.error>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -105,7 +105,7 @@ defmodule PlausibleWeb.Live.PropsSettings.Form do
|
||||||
class="mt-4 text-sm hover:underline text-indigo-600 dark:text-indigo-400 text-left"
|
class="mt-4 text-sm hover:underline text-indigo-600 dark:text-indigo-400 text-left"
|
||||||
phx-click="allow-existing-props"
|
phx-click="allow-existing-props"
|
||||||
>
|
>
|
||||||
Already sending custom properties? Click to add <%= @prop_key_options_count %> existing properties we found.
|
Already sending custom properties? Click to add {@prop_key_options_count} existing properties we found.
|
||||||
</button>
|
</button>
|
||||||
</.form>
|
</.form>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ defmodule PlausibleWeb.Live.PropsSettings.List do
|
||||||
<%= if is_list(@props) && length(@props) > 0 do %>
|
<%= if is_list(@props) && length(@props) > 0 do %>
|
||||||
<.table id="allowed-props" rows={Enum.with_index(@props)}>
|
<.table id="allowed-props" rows={Enum.with_index(@props)}>
|
||||||
<:tbody :let={{prop, index}}>
|
<:tbody :let={{prop, index}}>
|
||||||
<.td id={"prop-#{index}"}><span class="font-medium"><%= prop %></span></.td>
|
<.td id={"prop-#{index}"}><span class="font-medium">{prop}</span></.td>
|
||||||
<.td actions>
|
<.td actions>
|
||||||
<.delete_button
|
<.delete_button
|
||||||
id={"disallow-prop-#{prop}"}
|
id={"disallow-prop-#{prop}"}
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ defmodule PlausibleWeb.Live.RegisterForm do
|
||||||
def render(%{invitation_expired: true} = assigns) do
|
def render(%{invitation_expired: true} = assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<div class="mx-auto mt-6 text-center dark:text-gray-300">
|
<div class="mx-auto mt-6 text-center dark:text-gray-300">
|
||||||
<h1 class="text-3xl font-black"><%= Plausible.product_name() %></h1>
|
<h1 class="text-3xl font-black">{Plausible.product_name()}</h1>
|
||||||
<div class="text-xl font-medium">Lightweight and privacy-friendly web analytics</div>
|
<div class="text-xl font-medium">Lightweight and privacy-friendly web analytics</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -63,7 +63,7 @@ defmodule PlausibleWeb.Live.RegisterForm do
|
||||||
<div class="mx-auto text-center dark:text-gray-300">
|
<div class="mx-auto text-center dark:text-gray-300">
|
||||||
<h1 class="text-3xl font-black">
|
<h1 class="text-3xl font-black">
|
||||||
<%= if ce?() or @live_action == :register_from_invitation_form do %>
|
<%= if ce?() or @live_action == :register_from_invitation_form do %>
|
||||||
Register your <%= Plausible.product_name() %> account
|
Register your {Plausible.product_name()} account
|
||||||
<% else %>
|
<% else %>
|
||||||
Register your 30-day free trial
|
Register your 30-day free trial
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
@ -155,7 +155,7 @@ defmodule PlausibleWeb.Live.RegisterForm do
|
||||||
</div>
|
</div>
|
||||||
<%= if @captcha_error do %>
|
<%= if @captcha_error do %>
|
||||||
<div class="text-red-500 text-xs italic mt-3" x-data x-init="hcaptcha.reset()">
|
<div class="text-red-500 text-xs italic mt-3" x-data x-init="hcaptcha.reset()">
|
||||||
<%= @captcha_error %>
|
{@captcha_error}
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<script
|
<script
|
||||||
|
|
@ -176,7 +176,7 @@ defmodule PlausibleWeb.Live.RegisterForm do
|
||||||
"Start my free trial"
|
"Start my free trial"
|
||||||
end %>
|
end %>
|
||||||
<.button id="register" disabled={@disable_submit} type="submit" class="mt-4 w-full">
|
<.button id="register" disabled={@disable_submit} type="submit" class="mt-4 w-full">
|
||||||
<%= submit_text %>
|
{submit_text}
|
||||||
</.button>
|
</.button>
|
||||||
|
|
||||||
<p class="text-center text-gray-600 dark:text-gray-500 mt-4">
|
<p class="text-center text-gray-600 dark:text-gray-500 mt-4">
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ defmodule PlausibleWeb.Live.Shields.CountryRules do
|
||||||
theme={:gray}
|
theme={:gray}
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
You've reached the maximum number of countries you can block (<%= Shields.maximum_country_rules() %>). Please remove one before adding another.
|
You've reached the maximum number of countries you can block ({Shields.maximum_country_rules()}). Please remove one before adding another.
|
||||||
</p>
|
</p>
|
||||||
</.notice>
|
</.notice>
|
||||||
|
|
||||||
|
|
@ -76,7 +76,7 @@ defmodule PlausibleWeb.Live.Shields.CountryRules do
|
||||||
class="mr-4 cursor-help"
|
class="mr-4 cursor-help"
|
||||||
title={"Added at #{format_added_at(rule.inserted_at, @site.timezone)} by #{rule.added_by}"}
|
title={"Added at #{format_added_at(rule.inserted_at, @site.timezone)} by #{rule.added_by}"}
|
||||||
>
|
>
|
||||||
<%= country.flag %> <%= country.name %>
|
{country.flag} {country.name}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</.td>
|
</.td>
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,6 @@ defmodule PlausibleWeb.Live.Shields.HostnameRules do
|
||||||
alias Plausible.Shields
|
alias Plausible.Shields
|
||||||
alias Plausible.Shield
|
alias Plausible.Shield
|
||||||
|
|
||||||
import PlausibleWeb.ErrorHelpers
|
|
||||||
|
|
||||||
def update(assigns, socket) do
|
def update(assigns, socket) do
|
||||||
socket =
|
socket =
|
||||||
socket
|
socket
|
||||||
|
|
@ -58,7 +56,7 @@ defmodule PlausibleWeb.Live.Shields.HostnameRules do
|
||||||
theme={:gray}
|
theme={:gray}
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
You've reached the maximum number of hostnames you can block (<%= Shields.maximum_hostname_rules() %>). Please remove one before adding another.
|
You've reached the maximum number of hostnames you can block ({Shields.maximum_hostname_rules()}). Please remove one before adding another.
|
||||||
</p>
|
</p>
|
||||||
</.notice>
|
</.notice>
|
||||||
|
|
||||||
|
|
@ -83,7 +81,7 @@ defmodule PlausibleWeb.Live.Shields.HostnameRules do
|
||||||
class="mr-4 cursor-help text-ellipsis truncate max-w-xs"
|
class="mr-4 cursor-help text-ellipsis truncate max-w-xs"
|
||||||
title={"Added at #{format_added_at(rule.inserted_at, @site.timezone)} by #{rule.added_by}"}
|
title={"Added at #{format_added_at(rule.inserted_at, @site.timezone)} by #{rule.added_by}"}
|
||||||
>
|
>
|
||||||
<%= rule.hostname %>
|
{rule.hostname}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</.td>
|
</.td>
|
||||||
|
|
@ -136,12 +134,11 @@ defmodule PlausibleWeb.Live.Shields.HostnameRules do
|
||||||
id={"#{f[:hostname].id}-#{modal_unique_id}"}
|
id={"#{f[:hostname].id}-#{modal_unique_id}"}
|
||||||
creatable
|
creatable
|
||||||
/>
|
/>
|
||||||
|
<.error :for={msg <- f[:hostname].errors}>{translate_error(msg)}</.error>
|
||||||
<%= error_tag(f, :hostname) %>
|
|
||||||
|
|
||||||
<p class="mt-4 text-sm text-gray-500 dark:text-gray-400">
|
<p class="mt-4 text-sm text-gray-500 dark:text-gray-400">
|
||||||
You can use a wildcard (<code>*</code>) to match multiple hostnames. For example,
|
You can use a wildcard (<code>*</code>) to match multiple hostnames. For example,
|
||||||
<code>*<%= @site.domain %></code>
|
<code>*{@site.domain}</code>
|
||||||
will only record traffic on your main domain and all of its subdomains.<br /><br />
|
will only record traffic on your main domain and all of its subdomains.<br /><br />
|
||||||
|
|
||||||
<%= if @hostname_rules_count >= 1 do %>
|
<%= if @hostname_rules_count >= 1 do %>
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ defmodule PlausibleWeb.Live.Shields.IPRules do
|
||||||
theme={:gray}
|
theme={:gray}
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
You've reached the maximum number of IP addresses you can block (<%= Shields.maximum_ip_rules() %>). Please remove one before adding another.
|
You've reached the maximum number of IP addresses you can block ({Shields.maximum_ip_rules()}). Please remove one before adding another.
|
||||||
</p>
|
</p>
|
||||||
</.notice>
|
</.notice>
|
||||||
|
|
||||||
|
|
@ -83,7 +83,7 @@ defmodule PlausibleWeb.Live.Shields.IPRules do
|
||||||
class="cursor-help"
|
class="cursor-help"
|
||||||
title={"Added at #{format_added_at(rule.inserted_at, @site.timezone)} by #{rule.added_by}"}
|
title={"Added at #{format_added_at(rule.inserted_at, @site.timezone)} by #{rule.added_by}"}
|
||||||
>
|
>
|
||||||
<%= rule.inet %>
|
{rule.inet}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</.td>
|
</.td>
|
||||||
|
|
@ -97,7 +97,7 @@ defmodule PlausibleWeb.Live.Shields.IPRules do
|
||||||
</.td>
|
</.td>
|
||||||
<.td hide_on_mobile truncate>
|
<.td hide_on_mobile truncate>
|
||||||
<span :if={rule.description} title={rule.description}>
|
<span :if={rule.description} title={rule.description}>
|
||||||
<%= rule.description %>
|
{rule.description}
|
||||||
</span>
|
</span>
|
||||||
<span :if={!rule.description} class="text-gray-400 dark:text-gray-600">
|
<span :if={!rule.description} class="text-gray-400 dark:text-gray-600">
|
||||||
--
|
--
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,6 @@ defmodule PlausibleWeb.Live.Shields.PageRules do
|
||||||
alias Plausible.Shields
|
alias Plausible.Shields
|
||||||
alias Plausible.Shield
|
alias Plausible.Shield
|
||||||
|
|
||||||
import PlausibleWeb.ErrorHelpers
|
|
||||||
|
|
||||||
def update(assigns, socket) do
|
def update(assigns, socket) do
|
||||||
socket =
|
socket =
|
||||||
socket
|
socket
|
||||||
|
|
@ -58,7 +56,7 @@ defmodule PlausibleWeb.Live.Shields.PageRules do
|
||||||
theme={:gray}
|
theme={:gray}
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
You've reached the maximum number of pages you can block (<%= Shields.maximum_page_rules() %>). Please remove one before adding another.
|
You've reached the maximum number of pages you can block ({Shields.maximum_page_rules()}). Please remove one before adding another.
|
||||||
</p>
|
</p>
|
||||||
</.notice>
|
</.notice>
|
||||||
|
|
||||||
|
|
@ -79,7 +77,7 @@ defmodule PlausibleWeb.Live.Shields.PageRules do
|
||||||
class="mr-4 cursor-help text-ellipsis truncate max-w-xs"
|
class="mr-4 cursor-help text-ellipsis truncate max-w-xs"
|
||||||
title={"Added at #{format_added_at(rule.inserted_at, @site.timezone)} by #{rule.added_by}"}
|
title={"Added at #{format_added_at(rule.inserted_at, @site.timezone)} by #{rule.added_by}"}
|
||||||
>
|
>
|
||||||
<%= rule.page_path %>
|
{rule.page_path}
|
||||||
</span>
|
</span>
|
||||||
</.td>
|
</.td>
|
||||||
<.td hide_on_mobile>
|
<.td hide_on_mobile>
|
||||||
|
|
@ -132,7 +130,7 @@ defmodule PlausibleWeb.Live.Shields.PageRules do
|
||||||
creatable
|
creatable
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<%= error_tag(f, :page_path) %>
|
<.error :for={msg <- f[:page_path].errors}>{translate_error(msg)}</.error>
|
||||||
|
|
||||||
<p class="mt-4 text-sm text-gray-500 dark:text-gray-400">
|
<p class="mt-4 text-sm text-gray-500 dark:text-gray-400">
|
||||||
You can use a wildcard (<code>*</code>) to match multiple pages. For example,
|
You can use a wildcard (<code>*</code>) to match multiple pages. For example,
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ defmodule PlausibleWeb.Live.Sites do
|
||||||
page_number={@sites.page_number}
|
page_number={@sites.page_number}
|
||||||
total_pages={@sites.total_pages}
|
total_pages={@sites.total_pages}
|
||||||
>
|
>
|
||||||
Total of <span class="font-medium"><%= @sites.total_entries %></span> sites
|
Total of <span class="font-medium">{@sites.total_entries}</span> sites
|
||||||
</.pagination>
|
</.pagination>
|
||||||
<.invitation_modal :if={Enum.any?(@sites.entries, &(&1.entry_type == "invitation"))} />
|
<.invitation_modal :if={Enum.any?(@sites.entries, &(&1.entry_type == "invitation"))} />
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -166,7 +166,7 @@ defmodule PlausibleWeb.Live.Sites do
|
||||||
/>
|
/>
|
||||||
<div class="flex-1 truncate -mt-px">
|
<div class="flex-1 truncate -mt-px">
|
||||||
<h3 class="text-gray-900 font-medium text-lg truncate dark:text-gray-100">
|
<h3 class="text-gray-900 font-medium text-lg truncate dark:text-gray-100">
|
||||||
<%= @site.domain %>
|
{@site.domain}
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -212,7 +212,7 @@ defmodule PlausibleWeb.Live.Sites do
|
||||||
class="text-gray-900 font-medium text-lg truncate dark:text-gray-100"
|
class="text-gray-900 font-medium text-lg truncate dark:text-gray-100"
|
||||||
style="width: calc(100% - 4rem)"
|
style="width: calc(100% - 4rem)"
|
||||||
>
|
>
|
||||||
<%= @site.domain %>
|
{@site.domain}
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -308,7 +308,7 @@ defmodule PlausibleWeb.Live.Sites do
|
||||||
<div class="flex justify-between items-center">
|
<div class="flex justify-between items-center">
|
||||||
<p>
|
<p>
|
||||||
<span class="text-gray-800 dark:text-gray-200">
|
<span class="text-gray-800 dark:text-gray-200">
|
||||||
<b><%= PlausibleWeb.StatsView.large_number_format(@hourly_stats.visitors) %></b>
|
<b>{PlausibleWeb.StatsView.large_number_format(@hourly_stats.visitors)}</b>
|
||||||
visitor<span :if={@hourly_stats.visitors != 1}>s</span> in last 24h
|
visitor<span :if={@hourly_stats.visitors != 1}>s</span> in last 24h
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -357,7 +357,7 @@ defmodule PlausibleWeb.Live.Sites do
|
||||||
</path>
|
</path>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
<%= abs(@change) %>%
|
{abs(@change)}%
|
||||||
</p>
|
</p>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ defmodule PlausibleWeb.Router do
|
||||||
use PlausibleWeb, :router
|
use PlausibleWeb, :router
|
||||||
use Plausible
|
use Plausible
|
||||||
import Phoenix.LiveView.Router
|
import Phoenix.LiveView.Router
|
||||||
|
import PhoenixStorybook.Router
|
||||||
|
|
||||||
pipeline :browser do
|
pipeline :browser do
|
||||||
plug :accepts, ["html"]
|
plug :accepts, ["html"]
|
||||||
|
|
@ -77,6 +78,15 @@ defmodule PlausibleWeb.Router do
|
||||||
forward "/sent-emails", Bamboo.SentEmailViewerPlug
|
forward "/sent-emails", Bamboo.SentEmailViewerPlug
|
||||||
end
|
end
|
||||||
|
|
||||||
|
scope "/" do
|
||||||
|
storybook_assets()
|
||||||
|
end
|
||||||
|
|
||||||
|
scope "/", PlausibleWeb do
|
||||||
|
pipe_through :browser
|
||||||
|
live_storybook("/storybook", backend_module: PlausibleWeb.Storybook)
|
||||||
|
end
|
||||||
|
|
||||||
on_ee do
|
on_ee do
|
||||||
use Kaffy.Routes,
|
use Kaffy.Routes,
|
||||||
scope: "/crm",
|
scope: "/crm",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
defmodule PlausibleWeb.Storybook do
|
||||||
|
@moduledoc false
|
||||||
|
|
||||||
|
use PhoenixStorybook,
|
||||||
|
otp_app: :plausible_web,
|
||||||
|
title: "Plausible Storybook",
|
||||||
|
content_path: Path.expand("../../storybook", __DIR__),
|
||||||
|
# assets path are remote path, not local file-system paths
|
||||||
|
css_path: "/css/storybook.css",
|
||||||
|
js_path: "/js/storybook.js",
|
||||||
|
sandbox_class: "plausible",
|
||||||
|
color_mode: true
|
||||||
|
end
|
||||||
|
|
@ -18,13 +18,13 @@
|
||||||
|
|
||||||
<:subtitle :if={@has_email_code?}>
|
<:subtitle :if={@has_email_code?}>
|
||||||
<p class="truncate">
|
<p class="truncate">
|
||||||
Please enter the 4-digit code we sent to <b><%= @conn.assigns[:current_user].email %></b>
|
Please enter the 4-digit code we sent to <b>{@conn.assigns[:current_user].email}</b>
|
||||||
</p>
|
</p>
|
||||||
</:subtitle>
|
</:subtitle>
|
||||||
|
|
||||||
<:subtitle :if={!@has_email_code?}>
|
<:subtitle :if={!@has_email_code?}>
|
||||||
<p class="truncate">
|
<p class="truncate">
|
||||||
A 4-digit activation code will be sent to <b><%= @conn.assigns[:current_user].email %></b>
|
A 4-digit activation code will be sent to <b>{@conn.assigns[:current_user].email}</b>
|
||||||
</p>
|
</p>
|
||||||
</:subtitle>
|
</:subtitle>
|
||||||
|
|
||||||
|
|
@ -46,7 +46,7 @@
|
||||||
</.form>
|
</.form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= error_tag(assigns, :error) %>
|
<.error>{@error}</.error>
|
||||||
|
|
||||||
<div :if={!@has_email_code?}>
|
<div :if={!@has_email_code?}>
|
||||||
<.button_link method="post" class="w-full" href="/activate/request-code">
|
<.button_link method="post" class="w-full" href="/activate/request-code">
|
||||||
|
|
@ -65,7 +65,7 @@
|
||||||
<.styled_link href="/activate/request-code" method="post">
|
<.styled_link href="/activate/request-code" method="post">
|
||||||
Send a new code
|
Send a new code
|
||||||
</.styled_link>
|
</.styled_link>
|
||||||
to <%= @conn.assigns[:current_user].email %>
|
to {@conn.assigns[:current_user].email}
|
||||||
</:item>
|
</:item>
|
||||||
<:item :if={ee?()}>
|
<:item :if={ee?()}>
|
||||||
<.styled_link href="https://plausible.io/contact" new_tab={true}>
|
<.styled_link href="https://plausible.io/contact" new_tab={true}>
|
||||||
|
|
@ -88,7 +88,7 @@
|
||||||
<.styled_link method="post" href={Routes.settings_path(@conn, :cancel_update_email)}>
|
<.styled_link method="post" href={Routes.settings_path(@conn, :cancel_update_email)}>
|
||||||
Change email back to
|
Change email back to
|
||||||
</.styled_link>
|
</.styled_link>
|
||||||
<%= @conn.assigns[:current_user].previous_email %>
|
{@conn.assigns[:current_user].previous_email}
|
||||||
</:item>
|
</:item>
|
||||||
|
|
||||||
<:item :if={not @has_any_memberships?}>
|
<:item :if={not @has_any_memberships?}>
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
class="font-mono border-2 border-dotted border-gray-200 dark:border-gray-700 rounded-md text-gray-600 dark:text-gray-200 text-lg bg-gray-100 dark:bg-gray-900 p-2 mt-6 flex flex-wrap"
|
class="font-mono border-2 border-dotted border-gray-200 dark:border-gray-700 rounded-md text-gray-600 dark:text-gray-200 text-lg bg-gray-100 dark:bg-gray-900 p-2 mt-6 flex flex-wrap"
|
||||||
>
|
>
|
||||||
<%= for code <- @recovery_codes do %>
|
<%= for code <- @recovery_codes do %>
|
||||||
<div class="basis-1/2 text-center"><%= code %></div>
|
<div class="basis-1/2 text-center">{code}</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
<.focus_box>
|
<.focus_box>
|
||||||
<:title>
|
<:title>
|
||||||
<%= Phoenix.Flash.get(@flash, :login_title) || "Enter your account credentials" %>
|
{Phoenix.Flash.get(@flash, :login_title) || "Enter your account credentials"}
|
||||||
</:title>
|
</:title>
|
||||||
<:subtitle>
|
<:subtitle>
|
||||||
<%= if Phoenix.Flash.get(@flash, :login_instructions) do %>
|
<%= if Phoenix.Flash.get(@flash, :login_instructions) do %>
|
||||||
<p class="text-gray-500 mt-1 mb-2">
|
<p class="text-gray-500 mt-1 mb-2">
|
||||||
<%= Phoenix.Flash.get(@flash, :login_instructions) %>
|
{Phoenix.Flash.get(@flash, :login_instructions)}
|
||||||
</p>
|
</p>
|
||||||
<% end %>
|
<% end %>
|
||||||
</:subtitle>
|
</:subtitle>
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= if @conn.assigns[:error] do %>
|
<%= if @conn.assigns[:error] do %>
|
||||||
<div class="text-red-500 mt-4"><%= @conn.assigns[:error] %></div>
|
<div class="text-red-500 mt-4">{@conn.assigns[:error]}</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<.button class="w-full" type="submit">Log in</.button>
|
<.button class="w-full" type="submit">Log in</.button>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<%= live_render(@conn, PlausibleWeb.Live.ResetPasswordForm,
|
{live_render(@conn, PlausibleWeb.Live.ResetPasswordForm,
|
||||||
container: {:div, class: "contents"},
|
container: {:div, class: "contents"},
|
||||||
session: %{"email" => @email}
|
session: %{"email" => @email}
|
||||||
) %>
|
)}
|
||||||
|
|
|
||||||
|
|
@ -12,14 +12,14 @@
|
||||||
<.input type="email" field={f[:email]} placeholder="user@example.com" />
|
<.input type="email" field={f[:email]} placeholder="user@example.com" />
|
||||||
</div>
|
</div>
|
||||||
<%= if @conn.assigns[:error] do %>
|
<%= if @conn.assigns[:error] do %>
|
||||||
<div class="text-red-500 my-2"><%= @conn.assigns[:error] %></div>
|
<div class="text-red-500 my-2">{@conn.assigns[:error]}</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<%= if PlausibleWeb.Captcha.enabled?() do %>
|
<%= if PlausibleWeb.Captcha.enabled?() do %>
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<div class="h-captcha" data-sitekey={PlausibleWeb.Captcha.sitekey()}></div>
|
<div class="h-captcha" data-sitekey={PlausibleWeb.Captcha.sitekey()}></div>
|
||||||
<%= if assigns[:captcha_error] do %>
|
<%= if assigns[:captcha_error] do %>
|
||||||
<div class="text-red-500 text-xs mt-3"><%= @captcha_error %></div>
|
<div class="text-red-500 text-xs mt-3">{@captcha_error}</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<script src="https://hcaptcha.com/1/api.js" async defer>
|
<script src="https://hcaptcha.com/1/api.js" async defer>
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<div class="bg-white dark:bg-gray-800 max-w-md w-full mx-auto shadow-md rounded px-8 pt-6 pb-8 mb-4 mt-8">
|
<div class="bg-white dark:bg-gray-800 max-w-md w-full mx-auto shadow-md rounded px-8 pt-6 pb-8 mb-4 mt-8">
|
||||||
<h2 class="text-xl font-black dark:text-gray-100">Success!</h2>
|
<h2 class="text-xl font-black dark:text-gray-100">Success!</h2>
|
||||||
<div class="my-4 leading-tight dark:text-gray-100">
|
<div class="my-4 leading-tight dark:text-gray-100">
|
||||||
We've sent an email containing password reset instructions to <b><%= @email %></b>
|
We've sent an email containing password reset instructions to <b>{@email}</b>
|
||||||
if it's registered in our system.
|
if it's registered in our system.
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-8 text-sm dark:text-gray-100">
|
<div class="mt-8 text-sm dark:text-gray-100">
|
||||||
|
|
|
||||||
|
|
@ -25,12 +25,12 @@
|
||||||
<tbody class="bg-white dark:bg-gray-800">
|
<tbody class="bg-white dark:bg-gray-800">
|
||||||
<tr class="border-b border-gray-200">
|
<tr class="border-b border-gray-200">
|
||||||
<td class="px-6 py-4 text-sm leading-5 font-bold dark:text-gray-100">
|
<td class="px-6 py-4 text-sm leading-5 font-bold dark:text-gray-100">
|
||||||
<%= present_currency(@preview_info["immediate_payment"]["currency"]) %><%= @preview_info[
|
{present_currency(@preview_info["immediate_payment"]["currency"])}{@preview_info[
|
||||||
"immediate_payment"
|
"immediate_payment"
|
||||||
]["amount"] %>
|
]["amount"]}
|
||||||
</td>
|
</td>
|
||||||
<td class="px-6 py-4 text-sm leading-5 dark:text-gray-100">
|
<td class="px-6 py-4 text-sm leading-5 dark:text-gray-100">
|
||||||
<%= present_date(@preview_info["immediate_payment"]["date"]) %>
|
{present_date(@preview_info["immediate_payment"]["date"])}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
@ -60,12 +60,12 @@
|
||||||
<tbody class="bg-white dark:bg-gray-800">
|
<tbody class="bg-white dark:bg-gray-800">
|
||||||
<tr class="border-b border-gray-200">
|
<tr class="border-b border-gray-200">
|
||||||
<td class="px-6 py-4 text-sm leading-5 font-bold dark:text-gray-100">
|
<td class="px-6 py-4 text-sm leading-5 font-bold dark:text-gray-100">
|
||||||
<%= present_currency(@preview_info["immediate_payment"]["currency"]) %><%= @preview_info[
|
{present_currency(@preview_info["immediate_payment"]["currency"])}{@preview_info[
|
||||||
"next_payment"
|
"next_payment"
|
||||||
]["amount"] %>
|
]["amount"]}
|
||||||
</td>
|
</td>
|
||||||
<td class="px-6 py-4 text-sm leading-5 dark:text-gray-100">
|
<td class="px-6 py-4 text-sm leading-5 dark:text-gray-100">
|
||||||
<%= present_date(@preview_info["next_payment"]["date"]) %>
|
{present_date(@preview_info["next_payment"]["date"])}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<%= live_render(@conn, PlausibleWeb.Live.ChoosePlan,
|
{live_render(@conn, PlausibleWeb.Live.ChoosePlan,
|
||||||
id: "choose-plan",
|
id: "choose-plan",
|
||||||
session: %{"remote_ip" => PlausibleWeb.RemoteIP.get(@conn)}
|
session: %{"remote_ip" => PlausibleWeb.RemoteIP.get(@conn)}
|
||||||
) %>
|
)}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,19 @@
|
||||||
<div class="mx-auto mt-6 text-center">
|
<div class="mx-auto mt-6 text-center">
|
||||||
<h1 class="text-3xl font-black text-black dark:text-gray-100">
|
<h1 class="text-3xl font-black text-black dark:text-gray-100">
|
||||||
<%= if @subscription_resumable,
|
{if @subscription_resumable,
|
||||||
do: "Change subscription plan",
|
do: "Change subscription plan",
|
||||||
else: "Upgrade to Enterprise" %>
|
else: "Upgrade to Enterprise"}
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full max-w-lg px-4 mx-auto mt-4 text-gray-900 dark:text-gray-100">
|
<div class="w-full max-w-lg px-4 mx-auto mt-4 text-gray-900 dark:text-gray-100">
|
||||||
<div class="flex-1 p-8 mt-8 rounded bg-white shadow-md dark:bg-gray-800 dark:shadow-none">
|
<div class="flex-1 p-8 mt-8 rounded bg-white shadow-md dark:bg-gray-800 dark:shadow-none">
|
||||||
<div class="w-full pb-4">
|
<div class="w-full pb-4">
|
||||||
<span>
|
<span>
|
||||||
<%= if @subscription_resumable,
|
{if @subscription_resumable,
|
||||||
do:
|
do:
|
||||||
"We've prepared your account for an upgrade to custom limits outside the listed plans:",
|
"We've prepared your account for an upgrade to custom limits outside the listed plans:",
|
||||||
else:
|
else:
|
||||||
"We've prepared a custom enterprise plan for your account with the following limits:" %>
|
"We've prepared a custom enterprise plan for your account with the following limits:"}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<PlausibleWeb.Components.Billing.present_enterprise_plan plan={@latest_enterprise_plan} />
|
<PlausibleWeb.Components.Billing.present_enterprise_plan plan={@latest_enterprise_plan} />
|
||||||
|
|
@ -21,19 +21,19 @@
|
||||||
<span>
|
<span>
|
||||||
The plan is priced at
|
The plan is priced at
|
||||||
<b>
|
<b>
|
||||||
<%= case @price do
|
{case @price do
|
||||||
%Money{} = money -> Plausible.Billing.format_price(money)
|
%Money{} = money -> Plausible.Billing.format_price(money)
|
||||||
nil -> "N/A"
|
nil -> "N/A"
|
||||||
end %>
|
end}
|
||||||
</b>
|
</b>
|
||||||
</span>
|
</span>
|
||||||
<span>
|
<span>
|
||||||
per <%= if @latest_enterprise_plan.billing_interval == :yearly,
|
per {if @latest_enterprise_plan.billing_interval == :yearly,
|
||||||
do: "year",
|
do: "year",
|
||||||
else: "month" %> + VAT if applicable. <%= if @subscription_resumable,
|
else: "month"} + VAT if applicable. {if @subscription_resumable,
|
||||||
do:
|
do:
|
||||||
"On the next page, our payment provider will calculate the prorated amount that your card will be charged if you decide to upgrade now.",
|
"On the next page, our payment provider will calculate the prorated amount that your card will be charged if you decide to upgrade now.",
|
||||||
else: "Click the button below to upgrade." %>
|
else: "Click the button below to upgrade."}
|
||||||
</span>
|
</span>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="w-max">
|
<div class="w-max">
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@
|
||||||
<%= for log <- @queries do %>
|
<%= for log <- @queries do %>
|
||||||
<details class="group py-1">
|
<details class="group py-1">
|
||||||
<summary class="flex cursor-pointer flex-row items-center justify-between py-1 font-semibold text-gray-800 dark:text-gray-200 pt-4">
|
<summary class="flex cursor-pointer flex-row items-center justify-between py-1 font-semibold text-gray-800 dark:text-gray-200 pt-4">
|
||||||
<%= log["request_method"] %> <%= controller_name(log["phoenix_controller"]) %>.<%= log[
|
{log["request_method"]} {controller_name(log["phoenix_controller"])}.{log[
|
||||||
"phoenix_action"
|
"phoenix_action"
|
||||||
] %> (<%= log[:query_duration_ms] %>ms)
|
]} ({log[:query_duration_ms]}ms)
|
||||||
<svg
|
<svg
|
||||||
class="h-6 w-6 rotate-0 transform text-gray-400 dark:text-gray-200 group-open:rotate-180"
|
class="h-6 w-6 rotate-0 transform text-gray-400 dark:text-gray-200 group-open:rotate-180"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
<%= for {key, value} <- log do %>
|
<%= for {key, value} <- log do %>
|
||||||
<tr class="table-row">
|
<tr class="table-row">
|
||||||
<td class="table-cell p-2"><%= key %></td>
|
<td class="table-cell p-2">{key}</td>
|
||||||
<td class="table-cell p-2">
|
<td class="table-cell p-2">
|
||||||
<%= case key do %>
|
<%= case key do %>
|
||||||
<% :query -> %>
|
<% :query -> %>
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
<% "params" -> %>
|
<% "params" -> %>
|
||||||
<pre><%= Jason.encode!(value, pretty: true) %></pre>
|
<pre><%= Jason.encode!(value, pretty: true) %></pre>
|
||||||
<% _ -> %>
|
<% _ -> %>
|
||||||
<%= value %>
|
{value}
|
||||||
<% end %>
|
<% end %>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Enter <%= @code %> to verify your email address. This code will expire in 4 hours.
|
Enter {@code} to verify your email address. This code will expire in 4 hours.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
You used to have an active account with <%= Plausible.product_name() %>, a simple, lightweight, open source and privacy-first Google Analytics alternative.
|
You used to have an active account with {Plausible.product_name()}, a simple, lightweight, open source and privacy-first Google Analytics alternative.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
We've noticed that you're still sending us stats so we're writing to inform you that we'll stop accepting stats from your sites <%= @time %>. We're an independent, bootstrapped service and we don't sell your data, so this will reduce our server costs and help keep us sustainable.
|
We've noticed that you're still sending us stats so we're writing to inform you that we'll stop accepting stats from your sites {@time}. We're an independent, bootstrapped service and we don't sell your data, so this will reduce our server costs and help keep us sustainable.
|
||||||
<br /><br /> If you'd like to continue counting your site stats in a privacy-friendly way, please
|
<br /><br /> If you'd like to continue counting your site stats in a privacy-friendly way, please
|
||||||
<a href={plausible_url()}>login to your Plausible account</a> and start a subscription.
|
<a href={plausible_url()}>login to your Plausible account</a> and start a subscription.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,7 @@ You've activated
|
||||||
<%= if Plausible.ee?() do %>
|
<%= if Plausible.ee?() do %>
|
||||||
your free 30-day trial of
|
your free 30-day trial of
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= Plausible.product_name() %>, a simple and privacy-friendly website analytics tool.
|
{Plausible.product_name()}, a simple and privacy-friendly website analytics tool. <br /><br />
|
||||||
<br /><br />
|
|
||||||
<a href={"#{plausible_url()}/sites/new"}>Click here</a>
|
<a href={"#{plausible_url()}/sites/new"}>Click here</a>
|
||||||
to add your website URL, your timezone and install our one-line JavaScript snippet to start collecting visitor statistics.
|
to add your website URL, your timezone and install our one-line JavaScript snippet to start collecting visitor statistics.
|
||||||
<%= if Plausible.ee?() do %>
|
<%= if Plausible.ee?() do %>
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
<%= if @success do %>
|
<%= if @success do %>
|
||||||
Your CSV import has completed successfully. The Plausible dashboard for <%= @site_import.site.domain %> now contains historical imported data from <%= date_format(
|
Your CSV import has completed successfully. The Plausible dashboard for {@site_import.site.domain} now contains historical imported data from {date_format(
|
||||||
@site_import.start_date
|
@site_import.start_date
|
||||||
) %> to <%= date_format(@site_import.end_date) %>
|
)} to {date_format(@site_import.end_date)}
|
||||||
<br /><br />
|
<br /><br />
|
||||||
<a href={@link}>Click here</a>
|
<a href={@link}>Click here</a>
|
||||||
to view your dashboard.
|
to view your dashboard.
|
||||||
<% else %>
|
<% else %>
|
||||||
Unfortunately, your CSV import for <%= @site_import.site.domain %> did not complete successfully. Sorry about that!
|
Unfortunately, your CSV import for {@site_import.site.domain} did not complete successfully. Sorry about that!
|
||||||
<br /><br /> Please try to do the import once again.
|
<br /><br /> Please try to do the import once again.
|
||||||
<%= if ee?() do %>
|
<%= if ee?() do %>
|
||||||
<br /> <br />
|
<br /> <br />
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
Last week we sent a reminder that your site traffic has exceeded the limits of your <%= Plausible.product_name() %> subscription tier for two consecutive months. Since we haven't received a response, we've had to temporarily lock access to your stats.
|
Last week we sent a reminder that your site traffic has exceeded the limits of your {Plausible.product_name()} subscription tier for two consecutive months. Since we haven't received a response, we've had to temporarily lock access to your stats.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
Your subscription is still active, we're still counting your stats and haven't deleted any of your data but as you have outgrown your subscription tier, we kindly ask you to upgrade to match your new traffic levels. Upon upgrading to a suitable tier, your dashboard access will be immediately restored.
|
Your subscription is still active, we're still counting your stats and haven't deleted any of your data but as you have outgrown your subscription tier, we kindly ask you to upgrade to match your new traffic levels. Upon upgrading to a suitable tier, your dashboard access will be immediately restored.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
During the last billing cycle (<%= PlausibleWeb.TextHelpers.format_date_range(
|
During the last billing cycle ({PlausibleWeb.TextHelpers.format_date_range(
|
||||||
@usage.last_cycle.date_range
|
@usage.last_cycle.date_range
|
||||||
) %>), your account recorded <%= PlausibleWeb.AuthView.delimit_integer(@usage.last_cycle.total) %> billable pageviews. In the billing cycle before that (<%= PlausibleWeb.TextHelpers.format_date_range(
|
)}), your account recorded {PlausibleWeb.AuthView.delimit_integer(@usage.last_cycle.total)} billable pageviews. In the billing cycle before that ({PlausibleWeb.TextHelpers.format_date_range(
|
||||||
@usage.penultimate_cycle.date_range
|
@usage.penultimate_cycle.date_range
|
||||||
) %>), the usage was <%= PlausibleWeb.AuthView.delimit_integer(@usage.penultimate_cycle.total) %> billable pageviews. Note that billable pageviews include both standard pageviews and custom events. In your
|
)}), the usage was {PlausibleWeb.AuthView.delimit_integer(@usage.penultimate_cycle.total)} billable pageviews. Note that billable pageviews include both standard pageviews and custom events. In your
|
||||||
<a href={PlausibleWeb.Router.Helpers.settings_url(PlausibleWeb.Endpoint, :subscription)}>account settings</a>, you'll find an overview of your usage and limits.
|
<a href={PlausibleWeb.Router.Helpers.settings_url(PlausibleWeb.Endpoint, :subscription)}>account settings</a>, you'll find an overview of your usage and limits.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
<%= if @suggested_plan == :enterprise do %>
|
<%= if @suggested_plan == :enterprise do %>
|
||||||
Your usage exceeds our standard plans, so please reply back to this email for a tailored quote.
|
Your usage exceeds our standard plans, so please reply back to this email for a tailored quote.
|
||||||
<% else %>
|
<% else %>
|
||||||
<a href={PlausibleWeb.Router.Helpers.billing_url(PlausibleWeb.Endpoint, :choose_plan)}>Click here to upgrade your subscription</a>. We recommend you upgrade to the <%= @suggested_plan.volume %>/mo plan. The new charge will be prorated to reflect the amount you have already paid and the time until your current subscription is supposed to expire.
|
<a href={PlausibleWeb.Router.Helpers.billing_url(PlausibleWeb.Endpoint, :choose_plan)}>Click here to upgrade your subscription</a>. We recommend you upgrade to the {@suggested_plan.volume}/mo plan. The new charge will be prorated to reflect the amount you have already paid and the time until your current subscription is supposed to expire.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
If your usage decreases in the future, you can switch to a lower plan at any time. Any credit balance will automatically apply to future payments.
|
If your usage decreases in the future, you can switch to a lower plan at any time. Any credit balance will automatically apply to future payments.
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
We've recorded <%= @current_visitors %> visitors on
|
We've recorded {@current_visitors} visitors on
|
||||||
<a href={"https://" <> @site.domain}><%= @site.domain %></a> in the last 12 hours.
|
<a href={"https://" <> @site.domain}><%= @site.domain %></a> in the last 12 hours.
|
||||||
<%= if @dashboard_link do %>
|
<%= if @dashboard_link do %>
|
||||||
<br /><br /> View dashboard: <a href={@dashboard_link}><%= @dashboard_link %></a>
|
<br /><br /> View dashboard: <a href={@dashboard_link}>{@dashboard_link}</a>
|
||||||
<br /><br /> Something looks off? Please
|
<br /><br /> Something looks off? Please
|
||||||
<a href={@installation_link}>review your installation</a>
|
<a href={@installation_link}>review your installation</a>
|
||||||
to verify that Plausible has been integrated correctly.
|
to verify that Plausible has been integrated correctly.
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,14 @@
|
||||||
Automated notice about an enterprise account that has gone over their limits. <br /><br />
|
Automated notice about an enterprise account that has gone over their limits. <br /><br />
|
||||||
Customer email: <%= @user.email %><br />
|
Customer email: {@user.email}<br />
|
||||||
Last billing cycle: <%= PlausibleWeb.TextHelpers.format_date_range(
|
Last billing cycle: {PlausibleWeb.TextHelpers.format_date_range(
|
||||||
@pageview_usage.last_cycle.date_range
|
@pageview_usage.last_cycle.date_range
|
||||||
) %><br />
|
)}<br />
|
||||||
Last cycle pageview usage: <%= PlausibleWeb.AuthView.delimit_integer(
|
Last cycle pageview usage: {PlausibleWeb.AuthView.delimit_integer(
|
||||||
@pageview_usage.last_cycle.total
|
@pageview_usage.last_cycle.total
|
||||||
) %> billable pageviews<br />
|
)} billable pageviews<br />
|
||||||
Penultimate billing cycle: <%= PlausibleWeb.TextHelpers.format_date_range(
|
Penultimate billing cycle: {PlausibleWeb.TextHelpers.format_date_range(
|
||||||
@pageview_usage.penultimate_cycle.date_range
|
@pageview_usage.penultimate_cycle.date_range
|
||||||
) %><br />
|
)}<br />
|
||||||
Penultimate cycle pageview usage: <%= PlausibleWeb.AuthView.delimit_integer(
|
Penultimate cycle pageview usage: {PlausibleWeb.AuthView.delimit_integer(
|
||||||
@pageview_usage.penultimate_cycle.total
|
@pageview_usage.penultimate_cycle.total
|
||||||
) %> billable pageviews<br />
|
)} billable pageviews<br /> Site usage: {@site_usage} / {@site_allowance} allowed sites<br />
|
||||||
Site usage: <%= @site_usage %> / <%= @site_allowance %> allowed sites<br />
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<h1>Error report</h1>
|
<h1>Error report</h1>
|
||||||
<p>
|
<p>
|
||||||
Reported by: <%= @reported_by %>
|
Reported by: {@reported_by}
|
||||||
<br /> Sentry trace: <a href={sentry_link(@trace_id)}><%= @trace_id %></a>
|
<br /> Sentry trace: <a href={sentry_link(@trace_id)}>{@trace_id}</a>
|
||||||
<br />
|
<br />
|
||||||
</p>
|
</p>
|
||||||
<h2>User feedback:</h2>
|
<h2>User feedback:</h2>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
<%= @inviter.email %> has invited you to the <%= @site.domain %> site on <%= Plausible.product_name() %>.
|
{@inviter.email} has invited you to the {@site.domain} site on {Plausible.product_name()}.
|
||||||
<a href={Routes.site_url(PlausibleWeb.Endpoint, :index)}>Click here</a> to view and respond to the invitation. The invitation
|
<a href={Routes.site_url(PlausibleWeb.Endpoint, :index)}>Click here</a> to view and respond to the invitation. The invitation
|
||||||
will expire 48 hours after this email is sent.
|
will expire 48 hours after this email is sent.
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
<%= @inviter.email %> has invited you to the "<%= @team.name %>" team on <%= Plausible.product_name() %>.
|
{@inviter.email} has invited you to the "{@team.name}" team on {Plausible.product_name()}.
|
||||||
<a href={Routes.site_url(PlausibleWeb.Endpoint, :index)}>Click here</a> to view and respond to the invitation. The invitation
|
<a href={Routes.site_url(PlausibleWeb.Endpoint, :index)}>Click here</a> to view and respond to the invitation. The invitation
|
||||||
will expire 48 hours after this email is sent.
|
will expire 48 hours after this email is sent.
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
Your <%= Plausible.product_name() %> export for <%= @site.domain %> has encountered an error and was unsuccessful.
|
Your {Plausible.product_name()} export for {@site.domain} has encountered an error and was unsuccessful.
|
||||||
Sorry for the trouble this may have caused. <br /><br /> Please attempt to export your data again.
|
Sorry for the trouble this may have caused. <br /><br /> Please attempt to export your data again.
|
||||||
<%= if ee?() do %>
|
<%= if ee?() do %>
|
||||||
Should the problem persist, do reply to this email so we can assist. Thanks!
|
Should the problem persist, do reply to this email so we can assist. Thanks!
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
Your <%= Plausible.product_name() %> export for <%= @site.domain %> is now ready for download.
|
Your {Plausible.product_name()} export for {@site.domain} is now ready for download.
|
||||||
Please click <a href={@download_url}>here</a>
|
Please click <a href={@download_url}>here</a>
|
||||||
to start the download process.
|
to start the download process.
|
||||||
<%= if @expires_in do %>
|
<%= if @expires_in do %>
|
||||||
Note that this link will expire <%= @expires_in %>.
|
Note that this link will expire {@expires_in}.
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
<%= if @success do %>
|
<%= if @success do %>
|
||||||
Your Google Analytics import has completed successfully. The Plausible dashboard for <%= @site_import.site.domain %> now contains historical imported data from <%= date_format(
|
Your Google Analytics import has completed successfully. The Plausible dashboard for {@site_import.site.domain} now contains historical imported data from {date_format(
|
||||||
@site_import.start_date
|
@site_import.start_date
|
||||||
) %> to <%= date_format(@site_import.end_date) %>
|
)} to {date_format(@site_import.end_date)}
|
||||||
<br /><br />
|
<br /><br />
|
||||||
<a href={@link}>Click here</a>
|
<a href={@link}>Click here</a>
|
||||||
to view your dashboard.
|
to view your dashboard.
|
||||||
<% else %>
|
<% else %>
|
||||||
Unfortunately, your Google Analytics import for <%= @site_import.site.domain %> did not complete successfully. Sorry about that!
|
Unfortunately, your Google Analytics import for {@site_import.site.domain} did not complete successfully. Sorry about that!
|
||||||
<br /><br />
|
<br /><br />
|
||||||
Please try to do the import once again. Sometimes the Google Analytics API just randomly returns empty data. It's intermittent and random. Trying to do the import again may return what you need.
|
Please try to do the import once again. Sometimes the Google Analytics API just randomly returns empty data. It's intermittent and random. Trying to do the import again may return what you need.
|
||||||
<%= if ee?() do %>
|
<%= if ee?() do %>
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
<%= @invitee_email %> has accepted your invitation to <%= @site.domain %>.
|
{@invitee_email} has accepted your invitation to {@site.domain}.
|
||||||
<a href={Routes.site_url(PlausibleWeb.Endpoint, :settings_general, @site.domain)}>Click here</a> to view site settings.
|
<a href={Routes.site_url(PlausibleWeb.Endpoint, :settings_general, @site.domain)}>Click here</a> to view site settings.
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
<%= @guest_invitation.team_invitation.email %> has rejected your invitation to <%= @guest_invitation.site.domain %>.
|
{@guest_invitation.team_invitation.email} has rejected your invitation to {@guest_invitation.site.domain}.
|
||||||
<a href={Routes.site_url(PlausibleWeb.Endpoint, :settings_general, @guest_invitation.site.domain)}>Click here</a> to view site settings.
|
<a href={Routes.site_url(PlausibleWeb.Endpoint, :settings_general, @guest_invitation.site.domain)}>Click here</a> to view site settings.
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<%= @inviter.email %> has invited you to join the <%= @site.domain %> site on <%= Plausible.product_name() %>.
|
{@inviter.email} has invited you to join the {@site.domain} site on {Plausible.product_name()}.
|
||||||
<a href={
|
<a href={
|
||||||
Routes.auth_url(
|
Routes.auth_url(
|
||||||
PlausibleWeb.Endpoint,
|
PlausibleWeb.Endpoint,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<%= @inviter.email %> has invited you to join the "<%= @team.name %>" team on <%= Plausible.product_name() %>.
|
{@inviter.email} has invited you to join the "{@team.name}" team on {Plausible.product_name()}.
|
||||||
<a href={
|
<a href={
|
||||||
Routes.auth_url(
|
Routes.auth_url(
|
||||||
PlausibleWeb.Endpoint,
|
PlausibleWeb.Endpoint,
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,19 @@
|
||||||
Thanks for being a <%= Plausible.product_name() %> subscriber! <br /><br />
|
Thanks for being a {Plausible.product_name()} subscriber! <br /><br />
|
||||||
This is a friendly reminder that your traffic has exceeded your subscription tier for two consecutive months. Congrats on all that traffic!
|
This is a friendly reminder that your traffic has exceeded your subscription tier for two consecutive months. Congrats on all that traffic!
|
||||||
<br /><br />
|
<br /><br />
|
||||||
To maintain uninterrupted access to your stats, we kindly ask you to upgrade your account to match your new traffic levels. Please note, if your account isn't upgraded within the next 7 days, access to your stats will be temporarily locked.
|
To maintain uninterrupted access to your stats, we kindly ask you to upgrade your account to match your new traffic levels. Please note, if your account isn't upgraded within the next 7 days, access to your stats will be temporarily locked.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
During the last billing cycle (<%= PlausibleWeb.TextHelpers.format_date_range(
|
During the last billing cycle ({PlausibleWeb.TextHelpers.format_date_range(
|
||||||
@usage.last_cycle.date_range
|
@usage.last_cycle.date_range
|
||||||
) %>), your account recorded <%= PlausibleWeb.AuthView.delimit_integer(@usage.last_cycle.total) %> billable pageviews. In the billing cycle before that (<%= PlausibleWeb.TextHelpers.format_date_range(
|
)}), your account recorded {PlausibleWeb.AuthView.delimit_integer(@usage.last_cycle.total)} billable pageviews. In the billing cycle before that ({PlausibleWeb.TextHelpers.format_date_range(
|
||||||
@usage.penultimate_cycle.date_range
|
@usage.penultimate_cycle.date_range
|
||||||
) %>), your account used <%= PlausibleWeb.AuthView.delimit_integer(@usage.penultimate_cycle.total) %> billable pageviews. Note that billable pageviews include both standard pageviews and custom events. In your
|
)}), your account used {PlausibleWeb.AuthView.delimit_integer(@usage.penultimate_cycle.total)} billable pageviews. Note that billable pageviews include both standard pageviews and custom events. In your
|
||||||
<a href={plausible_url() <> PlausibleWeb.Router.Helpers.settings_path(PlausibleWeb.Endpoint, :subscription)}>account settings</a>, you'll find an overview of your usage and limits.
|
<a href={plausible_url() <> PlausibleWeb.Router.Helpers.settings_path(PlausibleWeb.Endpoint, :subscription)}>account settings</a>, you'll find an overview of your usage and limits.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
<%= if @suggested_plan == :enterprise do %>
|
<%= if @suggested_plan == :enterprise do %>
|
||||||
Your usage exceeds our standard plans, so please reply back to this email for a tailored quote.
|
Your usage exceeds our standard plans, so please reply back to this email for a tailored quote.
|
||||||
<% else %>
|
<% else %>
|
||||||
<a href={PlausibleWeb.Router.Helpers.billing_url(PlausibleWeb.Endpoint, :choose_plan)}>Click here to upgrade your subscription</a>. We recommend you upgrade to the <%= @suggested_plan.volume %>/mo plan. The new charge will be prorated to reflect the amount you have already paid and the time until your current subscription is supposed to expire.
|
<a href={PlausibleWeb.Router.Helpers.billing_url(PlausibleWeb.Endpoint, :choose_plan)}>Click here to upgrade your subscription</a>. We recommend you upgrade to the {@suggested_plan.volume}/mo plan. The new charge will be prorated to reflect the amount you have already paid and the time until your current subscription is supposed to expire.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
If your usage decreases in the future, you can switch to a lower plan at any time. Any credit balance will automatically apply to future payments.
|
If your usage decreases in the future, you can switch to a lower plan at any time. Any credit balance will automatically apply to future payments.
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
<%= @new_owner_email %> has accepted the ownership transfer of <%= @site.domain %>. They will be responsible for billing of it going
|
{@new_owner_email} has accepted the ownership transfer of {@site.domain}. They will be responsible for billing of it going
|
||||||
forward and your role has been changed to <b>admin</b>.
|
forward and your role has been changed to <b>admin</b>.
|
||||||
<a href={Routes.site_url(PlausibleWeb.Endpoint, :settings_general, @site.domain)}>Click here</a> to view site settings.
|
<a href={Routes.site_url(PlausibleWeb.Endpoint, :settings_general, @site.domain)}>Click here</a> to view site settings.
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
<%= @site_transfer.email %> has rejected the ownership transfer of <%= @site_transfer.site.domain %>.
|
{@site_transfer.email} has rejected the ownership transfer of {@site_transfer.site.domain}.
|
||||||
<a href={Routes.site_url(PlausibleWeb.Endpoint, :settings_general, @site_transfer.site.domain)}>Click here</a> to view site settings.
|
<a href={Routes.site_url(PlausibleWeb.Endpoint, :settings_general, @site_transfer.site.domain)}>Click here</a> to view site settings.
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<%= @inviter.email %> has requested to transfer the ownership of <%= @site.domain %> site on <%= Plausible.product_name() %> to you.
|
{@inviter.email} has requested to transfer the ownership of {@site.domain} site on {Plausible.product_name()} to you.
|
||||||
<%= if @new_owner_account do %>
|
<%= if @new_owner_account do %>
|
||||||
<a href={Routes.site_url(PlausibleWeb.Endpoint, :index)}>Click here</a>
|
<a href={Routes.site_url(PlausibleWeb.Endpoint, :index)}>Click here</a>
|
||||||
to view and respond to the invitation.
|
to view and respond to the invitation.
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
An administrator of <%= @guest_membership.site.domain %> has removed you as a member. You won't be able to see the stats anymore.
|
An administrator of {@guest_membership.site.domain} has removed you as a member. You won't be able to see the stats anymore.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
<a href={Routes.site_url(PlausibleWeb.Endpoint, :index)}>Click here</a>
|
<a href={Routes.site_url(PlausibleWeb.Endpoint, :index)}>Click here</a>
|
||||||
to view your sites.
|
to view your sites.
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
You signed up for a free 30-day trial of Plausible, a simple and privacy-friendly website analytics tool.
|
You signed up for a free 30-day trial of Plausible, a simple and privacy-friendly website analytics tool.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
<% end %>
|
<% end %>
|
||||||
To finish your setup for <%= @site.domain %>, review
|
To finish your setup for {@site.domain}, review
|
||||||
<a href={"#{plausible_url()}/#{URI.encode_www_form(@site.domain)}/installation"}>your installation</a> and start collecting visitor statistics.
|
<a href={"#{plausible_url()}/#{URI.encode_www_form(@site.domain)}/installation"}>your installation</a> and start collecting visitor statistics.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
This Plausible script is 45 times smaller than Google Analytics script so you’ll have a fast loading site while getting all the important traffic insights on one single page.
|
This Plausible script is 45 times smaller than Google Analytics script so you’ll have a fast loading site while getting all the important traffic insights on one single page.
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
There are currently <%= @current_visitors %> visitors on
|
There are currently {@current_visitors} visitors on
|
||||||
<a href={"https://" <> @site.domain}><%= @site.domain %></a>.
|
<a href={"https://" <> @site.domain}><%= @site.domain %></a>.
|
||||||
<%= if Enum.count(@sources) > 0 do %>
|
<%= if Enum.count(@sources) > 0 do %>
|
||||||
<br />
|
<br />
|
||||||
<br /> The top sources for current visitors:<br />
|
<br /> The top sources for current visitors:<br />
|
||||||
<%= for %{name: source, count: visitors} <- @sources do %>
|
<%= for %{name: source, count: visitors} <- @sources do %>
|
||||||
<%= source %> - <%= visitors %> visitor<%= if visitors > 1, do: "s" %><br />
|
{source} - {visitors} visitor{if visitors > 1, do: "s"}<br />
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<%= if @link do %>
|
<%= if @link do %>
|
||||||
<br /><br /> View dashboard: <a href={@link}><%= @link %></a>
|
<br /><br /> View dashboard: <a href={@link}>{@link}</a>
|
||||||
<% end %>
|
<% end %>
|
||||||
<br /><br /> Congrats on the spike in traffic!
|
<br /><br /> Congrats on the spike in traffic!
|
||||||
<%= if Plausible.ce? do %>
|
<%= if Plausible.ce? do %>
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
<%= @invitee_email %> has accepted your invitation to "<%= @team.name %>" team.
|
{@invitee_email} has accepted your invitation to "{@team.name}" team.
|
||||||
<a href={Routes.settings_url(PlausibleWeb.Endpoint, :team_general)}>Click here</a> to view team settings.
|
<a href={Routes.settings_url(PlausibleWeb.Endpoint, :team_general)}>Click here</a> to view team settings.
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
<%= @team_invitation.email %> has rejected your invitation to \"<%= @team_invitation.team.name %>\" team.
|
{@team_invitation.email} has rejected your invitation to \"{@team_invitation.team.name}\" team.
|
||||||
<a href={Routes.settings_url(PlausibleWeb.Endpoint, :team_general)}>Click here</a> to view team settings.
|
<a href={Routes.settings_url(PlausibleWeb.Endpoint, :team_general)}>Click here</a> to view team settings.
|
||||||
|
|
|
||||||
|
|
@ -4,5 +4,4 @@ Your free Plausible trial has now expired. Upgrade your account to continue rece
|
||||||
<a href={PlausibleWeb.Router.Helpers.billing_url(PlausibleWeb.Endpoint, :choose_plan)}>
|
<a href={PlausibleWeb.Router.Helpers.billing_url(PlausibleWeb.Endpoint, :choose_plan)}>
|
||||||
Upgrade now
|
Upgrade now
|
||||||
</a>
|
</a>
|
||||||
<br /><br />
|
<br /><br /> We will keep recording stats for {@extra_offset} days to give you time to upgrade.
|
||||||
We will keep recording stats for <%= @extra_offset %> days to give you time to upgrade.
|
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
Thanks for exploring Plausible, a simple and privacy-friendly alternative to Google Analytics. Your free 30-day trial is ending <%= @day %>, but you can keep using Plausible by upgrading to a paid plan.
|
Thanks for exploring Plausible, a simple and privacy-friendly alternative to Google Analytics. Your free 30-day trial is ending {@day}, but you can keep using Plausible by upgrading to a paid plan.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
In the last month, your account has used <%= PlausibleWeb.AuthView.delimit_integer(@usage) %> billable pageviews<%= if @custom_events >
|
In the last month, your account has used {PlausibleWeb.AuthView.delimit_integer(@usage)} billable pageviews{if @custom_events >
|
||||||
0,
|
0,
|
||||||
do:
|
do:
|
||||||
" and custom events in total",
|
" and custom events in total",
|
||||||
else:
|
else:
|
||||||
"" %>.
|
""}.
|
||||||
<%= if @suggested_plan == :enterprise do %>
|
<%= if @suggested_plan == :enterprise do %>
|
||||||
This is more than our standard plans, so please reply back to this email to get a quote for your volume.
|
This is more than our standard plans, so please reply back to this email to get a quote for your volume.
|
||||||
<% else %>
|
<% else %>
|
||||||
Based on that we recommend you select a <%= @suggested_plan.volume %>/mo plan. <br /><br />
|
Based on that we recommend you select a {@suggested_plan.volume}/mo plan. <br /><br />
|
||||||
<a href={PlausibleWeb.Router.Helpers.billing_url(PlausibleWeb.Endpoint, :choose_plan)}>
|
<a href={PlausibleWeb.Router.Helpers.billing_url(PlausibleWeb.Endpoint, :choose_plan)}>
|
||||||
Upgrade now
|
Upgrade now
|
||||||
</a>
|
</a>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
Time flies! This is a reminder that your annual subscription for <%= Plausible.product_name() %> will expire on <%= @next_bill_date %>.
|
Time flies! This is a reminder that your annual subscription for {Plausible.product_name()} will expire on {@next_bill_date}.
|
||||||
<br /><br /> You need to
|
<br /><br /> You need to
|
||||||
<a href={PlausibleWeb.Router.Helpers.billing_url(PlausibleWeb.Endpoint, :choose_plan)}>renew your subscription</a> if you want to continue using Plausible to count your website stats in a privacy-friendly way.
|
<a href={PlausibleWeb.Router.Helpers.billing_url(PlausibleWeb.Endpoint, :choose_plan)}>renew your subscription</a> if you want to continue using Plausible to count your website stats in a privacy-friendly way.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
If you don't want to continue your subscription, there's no action required. You will lose access to your dashboard on <%= @next_bill_date %> and we'll stop accepting stats on <%= @accept_traffic_until %>.
|
If you don't want to continue your subscription, there's no action required. You will lose access to your dashboard on {@next_bill_date} and we'll stop accepting stats on {@accept_traffic_until}.
|
||||||
<br /><br />
|
<br /><br />
|
||||||
Have a question, feedback or need some guidance? Just reply to this email to get in touch!
|
Have a question, feedback or need some guidance? Just reply to this email to get in touch!
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
Time flies! This is a reminder that your annual subscription for <%= Plausible.product_name() %> is due to renew on <%= @date %>. We will automatically charge <%= PlausibleWeb.BillingView.present_currency(
|
Time flies! This is a reminder that your annual subscription for {Plausible.product_name()} is due to renew on {@date}. We will automatically charge {PlausibleWeb.BillingView.present_currency(
|
||||||
@currency
|
@currency
|
||||||
) %><%= @next_bill_amount %> from your preferred billing method. <br /><br />
|
)}{@next_bill_amount} from your preferred billing method. <br /><br />
|
||||||
There's no action required if you're happy to continue using Plausible to count your website stats in a privacy-friendly way.
|
There's no action required if you're happy to continue using Plausible to count your website stats in a privacy-friendly way.
|
||||||
<br /><br /> If you don't want to continue your subscription, you can cancel it on your
|
<br /><br /> If you don't want to continue your subscription, you can cancel it on your
|
||||||
<a href={"#{plausible_url()}/settings"}>account settings page</a>. <br /><br />
|
<a href={"#{plausible_url()}/settings"}>account settings page</a>. <br /><br />
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<div class="container flex flex-col items-center text-center mt-24">
|
<div class="container flex flex-col items-center text-center mt-24">
|
||||||
<h1 class="text-5xl font-black dark:text-gray-100"><%= @status %></h1>
|
<h1 class="text-5xl font-black dark:text-gray-100">{@status}</h1>
|
||||||
<div class="mt-4 text-xl dark:text-gray-100">Oops! There's nothing here</div>
|
<div class="mt-4 text-xl dark:text-gray-100">Oops! There's nothing here</div>
|
||||||
<div class="text-xl dark:text-gray-100">
|
<div class="text-xl dark:text-gray-100">
|
||||||
Trying to access your dashboard? You may need to log in again to see it
|
Trying to access your dashboard? You may need to log in again to see it
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<div class="container text-center mt-24">
|
<div class="container text-center mt-24">
|
||||||
<h1 class="text-5xl font-black dark:text-gray-100"><%= @status %></h1>
|
<h1 class="text-5xl font-black dark:text-gray-100">{@status}</h1>
|
||||||
<div class="my-4 text-xl dark:text-gray-100"><%= @message %></div>
|
<div class="my-4 text-xl dark:text-gray-100">{@message}</div>
|
||||||
<.button_link href={PlausibleWeb.LayoutView.home_dest(@conn)}>Go to homepage</.button_link>
|
<.button_link href={PlausibleWeb.LayoutView.home_dest(@conn)}>Go to homepage</.button_link>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
<div class="mt-6">
|
<div class="mt-6">
|
||||||
<.label for={f[:property].id}>Google Analytics property</.label>
|
<.label for={f[:property].id}>Google Analytics property</.label>
|
||||||
<span class="block w-full text-base dark:text-gray-100 sm:text-sm dark:bg-gray-800">
|
<span class="block w-full text-base dark:text-gray-100 sm:text-sm dark:bg-gray-800">
|
||||||
<%= @selected_property_name %>
|
{@selected_property_name}
|
||||||
</span>
|
</span>
|
||||||
<.input type="hidden" value={@selected_property} field={f[:property]} readonly="true" />
|
<.input type="hidden" value={@selected_property} field={f[:property]} readonly="true" />
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
<div class="w-36">
|
<div class="w-36">
|
||||||
<.label for={f[:start_date].id}>From</.label>
|
<.label for={f[:start_date].id}>From</.label>
|
||||||
<span class="block w-full text-base dark:text-gray-100 sm:text-sm dark:bg-gray-800">
|
<span class="block w-full text-base dark:text-gray-100 sm:text-sm dark:bg-gray-800">
|
||||||
<%= PlausibleWeb.EmailView.date_format(@start_date) %>
|
{PlausibleWeb.EmailView.date_format(@start_date)}
|
||||||
</span>
|
</span>
|
||||||
<.input type="hidden" value={@start_date} field={f[:start_date]} readonly="true" />
|
<.input type="hidden" value={@start_date} field={f[:start_date]} readonly="true" />
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
<div class="w-36">
|
<div class="w-36">
|
||||||
<.label for={f[:end_date].id}>To</.label>
|
<.label for={f[:end_date].id}>To</.label>
|
||||||
<span class="block w-full text-base dark:text-gray-100 sm:text-sm dark:bg-gray-800">
|
<span class="block w-full text-base dark:text-gray-100 sm:text-sm dark:bg-gray-800">
|
||||||
<%= PlausibleWeb.EmailView.date_format(@end_date) %>
|
{PlausibleWeb.EmailView.date_format(@end_date)}
|
||||||
</span>
|
</span>
|
||||||
<.input type="hidden" value={@end_date} field={f[:end_date]} readonly="true" />
|
<.input type="hidden" value={@end_date} field={f[:end_date]} readonly="true" />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
</:title>
|
</:title>
|
||||||
|
|
||||||
<:subtitle>
|
<:subtitle>
|
||||||
Choose the property in your Google Analytics account that will be imported to the <%= @site.domain %> dashboard.
|
Choose the property in your Google Analytics account that will be imported to the {@site.domain} dashboard.
|
||||||
</:subtitle>
|
</:subtitle>
|
||||||
<.form
|
<.form
|
||||||
:let={f}
|
:let={f}
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<p class="text-red-600 dark:text-red-700">
|
<p class="text-red-600 dark:text-red-700">
|
||||||
<%= @conn.assigns[:selected_property_error] %>
|
{@conn.assigns[:selected_property_error]}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,10 +33,10 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-3 w-0 flex-1 pt-0.5">
|
<div class="ml-3 w-0 flex-1 pt-0.5">
|
||||||
<p class="text-sm leading-5 font-medium text-gray-900 dark:text-gray-100">
|
<p class="text-sm leading-5 font-medium text-gray-900 dark:text-gray-100">
|
||||||
<%= Phoenix.Flash.get(@flash, :success_title) || "Success!" %>
|
{Phoenix.Flash.get(@flash, :success_title) || "Success!"}
|
||||||
</p>
|
</p>
|
||||||
<p class="mt-1 text-sm leading-5 text-gray-500 dark:text-gray-200">
|
<p class="mt-1 text-sm leading-5 text-gray-500 dark:text-gray-200">
|
||||||
<%= Phoenix.Flash.get(@flash, :success) %>
|
{Phoenix.Flash.get(@flash, :success)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-4 flex-shrink-0 flex">
|
<div class="ml-4 flex-shrink-0 flex">
|
||||||
|
|
@ -102,10 +102,10 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-3 w-0 flex-1 pt-0.5">
|
<div class="ml-3 w-0 flex-1 pt-0.5">
|
||||||
<p class="text-sm leading-5 font-medium text-gray-900 dark:text-gray-100">
|
<p class="text-sm leading-5 font-medium text-gray-900 dark:text-gray-100">
|
||||||
<%= Phoenix.Flash.get(@flash, :error_title) || "Error" %>
|
{Phoenix.Flash.get(@flash, :error_title) || "Error"}
|
||||||
</p>
|
</p>
|
||||||
<p class="mt-1 text-sm leading-5 text-gray-500 dark:text-gray-200">
|
<p class="mt-1 text-sm leading-5 text-gray-500 dark:text-gray-200">
|
||||||
<%= Phoenix.Flash.get(@flash, :error) %>
|
{Phoenix.Flash.get(@flash, :error)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-4 flex-shrink-0 flex">
|
<div class="ml-4 flex-shrink-0 flex">
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue