Starter Tier: Teams UI follow-ups (#5456)
* keep teams feature explicitly for UI * keep devsubscriptions in sync with prod On prod, when a subscription is created without a current team in assings, a new team is force created for that user. * disable team creation when no point to create it * fix ce_test compile warning * fix tests on CE * Update lib/plausible/teams/billing.ex Co-authored-by: hq1 <hq@mtod.org> * add solo team in seeds * fix top border blur + stop autofocusing input when blurred --------- Co-authored-by: hq1 <hq@mtod.org>
This commit is contained in:
parent
a01f8e1c05
commit
38f1de6ecd
|
|
@ -72,7 +72,6 @@ defmodule Plausible.Billing.Feature do
|
||||||
|
|
||||||
@features [
|
@features [
|
||||||
Plausible.Billing.Feature.Props,
|
Plausible.Billing.Feature.Props,
|
||||||
Plausible.Billing.Feature.Teams,
|
|
||||||
Plausible.Billing.Feature.SharedLinks,
|
Plausible.Billing.Feature.SharedLinks,
|
||||||
Plausible.Billing.Feature.Funnels,
|
Plausible.Billing.Feature.Funnels,
|
||||||
Plausible.Billing.Feature.Goals,
|
Plausible.Billing.Feature.Goals,
|
||||||
|
|
@ -200,13 +199,6 @@ defmodule Plausible.Billing.Feature.Props do
|
||||||
toggle_field: :props_enabled
|
toggle_field: :props_enabled
|
||||||
end
|
end
|
||||||
|
|
||||||
defmodule Plausible.Billing.Feature.Teams do
|
|
||||||
@moduledoc false
|
|
||||||
use Plausible.Billing.Feature,
|
|
||||||
name: :teams,
|
|
||||||
display_name: "Team Management"
|
|
||||||
end
|
|
||||||
|
|
||||||
defmodule Plausible.Billing.Feature.SharedLinks do
|
defmodule Plausible.Billing.Feature.SharedLinks do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
use Plausible.Billing.Feature,
|
use Plausible.Billing.Feature,
|
||||||
|
|
@ -238,3 +230,19 @@ defmodule Plausible.Billing.Feature.SitesAPI do
|
||||||
name: :sites_api,
|
name: :sites_api,
|
||||||
display_name: "Sites API"
|
display_name: "Sites API"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defmodule Plausible.Billing.Feature.Teams do
|
||||||
|
@moduledoc """
|
||||||
|
Unlike other feature modules, this one only exists to make feature gating
|
||||||
|
settings views more convenient. Other than that, it's not even considered
|
||||||
|
a feature on its own. The real access to "Teams" is controlled by the
|
||||||
|
team member limit.
|
||||||
|
"""
|
||||||
|
def check_availability(team) do
|
||||||
|
if Plausible.Teams.Billing.solo?(team) do
|
||||||
|
{:error, :upgrade_required}
|
||||||
|
else
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
||||||
|
|
@ -235,8 +235,16 @@ defmodule Plausible.Teams.Billing do
|
||||||
nil -> @team_member_limit_for_trials
|
nil -> @team_member_limit_for_trials
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def solo?(nil), do: true
|
||||||
|
|
||||||
|
def solo?(team) do
|
||||||
|
team_member_limit(team) == 0
|
||||||
|
end
|
||||||
else
|
else
|
||||||
def team_member_limit(_team), do: :unlimited
|
def team_member_limit(_team), do: :unlimited
|
||||||
|
|
||||||
|
def solo?(_team), do: false
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
|
|
@ -605,19 +613,19 @@ defmodule Plausible.Teams.Billing do
|
||||||
|
|
||||||
case Plans.get_subscription_plan(team.subscription) do
|
case Plans.get_subscription_plan(team.subscription) do
|
||||||
%EnterprisePlan{features: features} ->
|
%EnterprisePlan{features: features} ->
|
||||||
features ++ [Feature.Teams, SharedLinks]
|
features ++ [SharedLinks]
|
||||||
|
|
||||||
%Plan{features: features} ->
|
%Plan{features: features} ->
|
||||||
features
|
features
|
||||||
|
|
||||||
:free_10k ->
|
:free_10k ->
|
||||||
[Goals, Props, StatsAPI, Feature.Teams, SharedLinks]
|
[Goals, Props, StatsAPI, SharedLinks]
|
||||||
|
|
||||||
nil ->
|
nil ->
|
||||||
if Teams.on_trial?(team) do
|
if Teams.on_trial?(team) do
|
||||||
Feature.list() -- [SitesAPI]
|
Feature.list() -- [SitesAPI]
|
||||||
else
|
else
|
||||||
[Goals, Feature.Teams, SharedLinks]
|
[Goals, SharedLinks]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -5,21 +5,14 @@ defmodule PlausibleWeb.Components.Billing do
|
||||||
use Plausible
|
use Plausible
|
||||||
|
|
||||||
require Plausible.Billing.Subscription.Status
|
require Plausible.Billing.Subscription.Status
|
||||||
alias Plausible.Billing.{Subscription, Subscriptions, Feature, Plan, Plans, EnterprisePlan}
|
alias Plausible.Billing.{Subscription, Subscriptions, Plan, Plans, EnterprisePlan}
|
||||||
|
|
||||||
attr :current_role, :atom, required: true
|
attr :current_role, :atom, required: true
|
||||||
attr :current_team, :any, required: true
|
attr :current_team, :any, required: true
|
||||||
attr :feature_mod, :atom, required: true, values: Feature.list()
|
attr :locked?, :boolean, required: true
|
||||||
slot :inner_block, required: true
|
slot :inner_block, required: true
|
||||||
|
|
||||||
def feature_gate(assigns) do
|
def feature_gate(assigns) do
|
||||||
assigns =
|
|
||||||
assign(
|
|
||||||
assigns,
|
|
||||||
:locked?,
|
|
||||||
assigns.feature_mod.check_availability(assigns.current_team) != :ok
|
|
||||||
)
|
|
||||||
|
|
||||||
~H"""
|
~H"""
|
||||||
<div id="feature-gate-inner-block-container" class={if(@locked?, do: "pointer-events-none")}>
|
<div id="feature-gate-inner-block-container" class={if(@locked?, do: "pointer-events-none")}>
|
||||||
{render_slot(@inner_block)}
|
{render_slot(@inner_block)}
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,8 @@ defmodule PlausibleWeb.Components.Billing.PlanBenefits do
|
||||||
[
|
[
|
||||||
"Everything in Starter",
|
"Everything in Starter",
|
||||||
site_limit_benefit(growth_plan),
|
site_limit_benefit(growth_plan),
|
||||||
team_member_limit_benefit(growth_plan)
|
team_member_limit_benefit(growth_plan),
|
||||||
|
"Team Management"
|
||||||
]
|
]
|
||||||
|> Kernel.++(feature_benefits(growth_plan))
|
|> Kernel.++(feature_benefits(growth_plan))
|
||||||
|> Kernel.--(starter_benefits)
|
|> Kernel.--(starter_benefits)
|
||||||
|
|
|
||||||
|
|
@ -472,7 +472,7 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<%= if @feature_mod do %>
|
<%= if @feature_mod do %>
|
||||||
<PlausibleWeb.Components.Billing.feature_gate
|
<PlausibleWeb.Components.Billing.feature_gate
|
||||||
feature_mod={@feature_mod}
|
locked?={@feature_mod.check_availability(@current_team) != :ok}
|
||||||
current_role={@current_role}
|
current_role={@current_role}
|
||||||
current_team={@current_team}
|
current_team={@current_team}
|
||||||
>
|
>
|
||||||
|
|
@ -634,6 +634,7 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
slot :subtitle
|
slot :subtitle
|
||||||
slot :inner_block, required: true
|
slot :inner_block, required: true
|
||||||
slot :footer
|
slot :footer
|
||||||
|
attr :padding?, :boolean, default: true
|
||||||
attr :rest, :global
|
attr :rest, :global
|
||||||
|
|
||||||
def focus_box(assigns) do
|
def focus_box(assigns) do
|
||||||
|
|
@ -642,7 +643,7 @@ defmodule PlausibleWeb.Components.Generic do
|
||||||
class="bg-white w-full max-w-lg mx-auto dark:bg-gray-800 text-gray-900 dark:text-gray-100 shadow-md rounded-md mt-12"
|
class="bg-white w-full max-w-lg mx-auto dark:bg-gray-800 text-gray-900 dark:text-gray-100 shadow-md rounded-md mt-12"
|
||||||
{@rest}
|
{@rest}
|
||||||
>
|
>
|
||||||
<div class="p-8">
|
<div class={if(@padding?, do: "p-8")}>
|
||||||
<.title :if={@title != []}>
|
<.title :if={@title != []}>
|
||||||
{render_slot(@title)}
|
{render_slot(@title)}
|
||||||
</.title>
|
</.title>
|
||||||
|
|
|
||||||
|
|
@ -55,10 +55,12 @@ defmodule PlausibleWeb.Live.TeamSetup do
|
||||||
end
|
end
|
||||||
|
|
||||||
def render(assigns) do
|
def render(assigns) do
|
||||||
|
assigns = assign(assigns, :locked?, Plausible.Teams.Billing.solo?(assigns.current_team))
|
||||||
|
|
||||||
~H"""
|
~H"""
|
||||||
<.focus_box>
|
<.focus_box padding?={false}>
|
||||||
<:title>
|
<:title>
|
||||||
<div class="flex justify-between">
|
<div class="pt-8 px-8 flex justify-between">
|
||||||
<div>Create a new team</div>
|
<div>Create a new team</div>
|
||||||
<div class="ml-auto">
|
<div class="ml-auto">
|
||||||
<.docs_info slug="users-roles" />
|
<.docs_info slug="users-roles" />
|
||||||
|
|
@ -66,9 +68,17 @@ defmodule PlausibleWeb.Live.TeamSetup do
|
||||||
</div>
|
</div>
|
||||||
</:title>
|
</:title>
|
||||||
<:subtitle>
|
<:subtitle>
|
||||||
|
<p class="px-8">
|
||||||
Name your team, add team members and assign roles. When ready, click "Create Team" to send invitations
|
Name your team, add team members and assign roles. When ready, click "Create Team" to send invitations
|
||||||
|
</p>
|
||||||
</:subtitle>
|
</:subtitle>
|
||||||
|
|
||||||
|
<div class="relative -mt-8 pt-4 pb-8 px-8">
|
||||||
|
<PlausibleWeb.Components.Billing.feature_gate
|
||||||
|
current_role={@current_team_role}
|
||||||
|
current_team={@current_team}
|
||||||
|
locked?={@locked?}
|
||||||
|
>
|
||||||
<.form
|
<.form
|
||||||
:let={f}
|
:let={f}
|
||||||
for={@team_name_form}
|
for={@team_name_form}
|
||||||
|
|
@ -81,7 +91,7 @@ defmodule PlausibleWeb.Live.TeamSetup do
|
||||||
<.input
|
<.input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={"#{@current_user.name}'s Team"}
|
placeholder={"#{@current_user.name}'s Team"}
|
||||||
autofocus
|
autofocus={not @locked?}
|
||||||
field={f[:name]}
|
field={f[:name]}
|
||||||
label="Name"
|
label="Name"
|
||||||
width="w-full"
|
width="w-full"
|
||||||
|
|
@ -99,6 +109,8 @@ defmodule PlausibleWeb.Live.TeamSetup do
|
||||||
"mode" => "team-setup"
|
"mode" => "team-setup"
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
|
</PlausibleWeb.Components.Billing.feature_gate>
|
||||||
|
</div>
|
||||||
</.focus_box>
|
</.focus_box>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -92,10 +92,7 @@
|
||||||
Account Settings
|
Account Settings
|
||||||
</.dropdown_item>
|
</.dropdown_item>
|
||||||
|
|
||||||
<div :if={
|
<div :if={@my_team && @my_team.id == @current_team.id}>
|
||||||
@my_team && @my_team.id == @current_team.id &&
|
|
||||||
Plausible.Billing.Feature.Teams.check_availability(@current_team) == :ok
|
|
||||||
}>
|
|
||||||
<.dropdown_item class="flex" href={Routes.team_setup_path(@conn, :setup)}>
|
<.dropdown_item class="flex" href={Routes.team_setup_path(@conn, :setup)}>
|
||||||
<span data-test="create-a-team-cta" class="flex-1">
|
<span data-test="create-a-team-cta" class="flex-1">
|
||||||
Create a Team
|
Create a Team
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<.settings_tiles>
|
<.settings_tiles>
|
||||||
<%= if not Plausible.Teams.setup?(@site.team) and Plausible.Billing.Feature.Teams.check_availability(@site.team) == :ok do %>
|
<%= if not Plausible.Teams.setup?(@site.team) and not Plausible.Teams.Billing.solo?(@site.team) do %>
|
||||||
<PlausibleWeb.Team.Notice.owner_cta_banner :if={@site_role == :owner} />
|
<PlausibleWeb.Team.Notice.owner_cta_banner :if={@site_role == :owner} />
|
||||||
<PlausibleWeb.Team.Notice.guest_cta_banner :if={@site_role != :owner} />
|
<PlausibleWeb.Team.Notice.guest_cta_banner :if={@site_role != :owner} />
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -27,7 +26,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -43,7 +41,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -59,7 +56,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -75,7 +71,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -91,7 +86,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -107,7 +101,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -123,7 +116,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -139,7 +131,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -155,7 +146,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -27,7 +26,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -43,7 +41,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -59,7 +56,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -75,7 +71,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -91,7 +86,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -107,7 +101,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -123,7 +116,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -139,7 +131,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -155,7 +146,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -27,7 +26,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -43,7 +41,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -59,7 +56,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -75,7 +71,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -91,7 +86,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -107,7 +101,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -123,7 +116,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -142,7 +134,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -161,7 +152,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -180,7 +170,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -199,7 +188,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -218,7 +206,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -237,7 +224,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -256,7 +242,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -275,7 +260,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 3
|
"data_retention_in_years": 3
|
||||||
|
|
@ -24,7 +23,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 3
|
"data_retention_in_years": 3
|
||||||
|
|
@ -39,7 +37,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 3
|
"data_retention_in_years": 3
|
||||||
|
|
@ -54,7 +51,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 3
|
"data_retention_in_years": 3
|
||||||
|
|
@ -69,7 +65,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 3
|
"data_retention_in_years": 3
|
||||||
|
|
@ -84,7 +79,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 3
|
"data_retention_in_years": 3
|
||||||
|
|
@ -99,7 +93,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 3
|
"data_retention_in_years": 3
|
||||||
|
|
@ -114,7 +107,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 3
|
"data_retention_in_years": 3
|
||||||
|
|
@ -134,7 +126,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 5
|
"data_retention_in_years": 5
|
||||||
|
|
@ -154,7 +145,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 5
|
"data_retention_in_years": 5
|
||||||
|
|
@ -174,7 +164,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 5
|
"data_retention_in_years": 5
|
||||||
|
|
@ -194,7 +183,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 5
|
"data_retention_in_years": 5
|
||||||
|
|
@ -214,7 +202,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 5
|
"data_retention_in_years": 5
|
||||||
|
|
@ -234,7 +221,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 5
|
"data_retention_in_years": 5
|
||||||
|
|
@ -254,7 +240,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 5
|
"data_retention_in_years": 5
|
||||||
|
|
@ -274,7 +259,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 5
|
"data_retention_in_years": 5
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments"
|
"site_segments"
|
||||||
],
|
],
|
||||||
|
|
@ -129,7 +128,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments"
|
"site_segments"
|
||||||
],
|
],
|
||||||
|
|
@ -145,7 +143,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments"
|
"site_segments"
|
||||||
],
|
],
|
||||||
|
|
@ -161,7 +158,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments"
|
"site_segments"
|
||||||
],
|
],
|
||||||
|
|
@ -177,7 +173,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments"
|
"site_segments"
|
||||||
],
|
],
|
||||||
|
|
@ -193,7 +188,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments"
|
"site_segments"
|
||||||
],
|
],
|
||||||
|
|
@ -209,7 +203,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments"
|
"site_segments"
|
||||||
],
|
],
|
||||||
|
|
@ -225,7 +218,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments"
|
"site_segments"
|
||||||
],
|
],
|
||||||
|
|
@ -241,7 +233,6 @@
|
||||||
"team_member_limit": 10,
|
"team_member_limit": 10,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"props",
|
"props",
|
||||||
|
|
@ -261,7 +252,6 @@
|
||||||
"team_member_limit": 10,
|
"team_member_limit": 10,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"props",
|
"props",
|
||||||
|
|
@ -281,7 +271,6 @@
|
||||||
"team_member_limit": 10,
|
"team_member_limit": 10,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"props",
|
"props",
|
||||||
|
|
@ -301,7 +290,6 @@
|
||||||
"team_member_limit": 10,
|
"team_member_limit": 10,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"props",
|
"props",
|
||||||
|
|
@ -321,7 +309,6 @@
|
||||||
"team_member_limit": 10,
|
"team_member_limit": 10,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"props",
|
"props",
|
||||||
|
|
@ -341,7 +328,6 @@
|
||||||
"team_member_limit": 10,
|
"team_member_limit": 10,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"props",
|
"props",
|
||||||
|
|
@ -361,7 +347,6 @@
|
||||||
"team_member_limit": 10,
|
"team_member_limit": 10,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"props",
|
"props",
|
||||||
|
|
@ -381,7 +366,6 @@
|
||||||
"team_member_limit": 10,
|
"team_member_limit": 10,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"props",
|
"props",
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@ use Plausible
|
||||||
|
|
||||||
import Plausible.Teams.Test
|
import Plausible.Teams.Test
|
||||||
|
|
||||||
|
FunWithFlags.enable(:starter_tier)
|
||||||
|
|
||||||
words =
|
words =
|
||||||
for i <- 0..(:erlang.system_info(:atom_count) - 1),
|
for i <- 0..(:erlang.system_info(:atom_count) - 1),
|
||||||
do: :erlang.binary_to_term(<<131, 75, i::24>>)
|
do: :erlang.binary_to_term(<<131, 75, i::24>>)
|
||||||
|
|
@ -66,6 +68,11 @@ user2 = new_user(name: "Mary Jane", email: "user2@plausible.test", password: "pl
|
||||||
site2 = new_site(domain: "computer.example.com", owner: user2)
|
site2 = new_site(domain: "computer.example.com", owner: user2)
|
||||||
invite_guest(site2, user, inviter: user2, role: :viewer)
|
invite_guest(site2, user, inviter: user2, role: :viewer)
|
||||||
|
|
||||||
|
solo_user = new_user(name: "Solo User", email: "solo@plausible.test", password: "plausible")
|
||||||
|
new_site(domain: "mysolosite.com", owner: solo_user)
|
||||||
|
{:ok, solo_team} = Plausible.Teams.get_or_create(solo_user)
|
||||||
|
Plausible.Billing.DevSubscriptions.create(solo_team.id, "910413")
|
||||||
|
|
||||||
Plausible.Factory.insert_list(29, :ip_rule, site: site)
|
Plausible.Factory.insert_list(29, :ip_rule, site: site)
|
||||||
Plausible.Factory.insert(:country_rule, site: site, country_code: "PL")
|
Plausible.Factory.insert(:country_rule, site: site, country_code: "PL")
|
||||||
Plausible.Factory.insert(:country_rule, site: site, country_code: "EE")
|
Plausible.Factory.insert(:country_rule, site: site, country_code: "EE")
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -27,7 +26,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -43,7 +41,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -59,7 +56,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -75,7 +71,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -91,7 +86,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -107,7 +101,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -123,7 +116,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -139,7 +131,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -155,7 +146,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -27,7 +26,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -43,7 +41,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -59,7 +56,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -75,7 +71,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -91,7 +86,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -107,7 +101,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -123,7 +116,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -139,7 +131,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -155,7 +146,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -27,7 +26,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -43,7 +41,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -59,7 +56,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -75,7 +71,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -91,7 +86,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -107,7 +101,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -123,7 +116,6 @@
|
||||||
"goals",
|
"goals",
|
||||||
"props",
|
"props",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -142,7 +134,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -161,7 +152,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -180,7 +170,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -199,7 +188,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -218,7 +206,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -237,7 +224,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -256,7 +242,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -275,7 +260,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 3
|
"data_retention_in_years": 3
|
||||||
|
|
@ -24,7 +23,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 3
|
"data_retention_in_years": 3
|
||||||
|
|
@ -39,7 +37,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 3
|
"data_retention_in_years": 3
|
||||||
|
|
@ -54,7 +51,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 3
|
"data_retention_in_years": 3
|
||||||
|
|
@ -69,7 +65,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 3
|
"data_retention_in_years": 3
|
||||||
|
|
@ -84,7 +79,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 3
|
"data_retention_in_years": 3
|
||||||
|
|
@ -99,7 +93,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 3
|
"data_retention_in_years": 3
|
||||||
|
|
@ -114,7 +107,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 3
|
"data_retention_in_years": 3
|
||||||
|
|
@ -134,7 +126,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 5
|
"data_retention_in_years": 5
|
||||||
|
|
@ -154,7 +145,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 5
|
"data_retention_in_years": 5
|
||||||
|
|
@ -174,7 +164,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 5
|
"data_retention_in_years": 5
|
||||||
|
|
@ -194,7 +183,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 5
|
"data_retention_in_years": 5
|
||||||
|
|
@ -214,7 +202,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 5
|
"data_retention_in_years": 5
|
||||||
|
|
@ -234,7 +221,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 5
|
"data_retention_in_years": 5
|
||||||
|
|
@ -254,7 +240,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 5
|
"data_retention_in_years": 5
|
||||||
|
|
@ -274,7 +259,6 @@
|
||||||
"funnels",
|
"funnels",
|
||||||
"stats_api",
|
"stats_api",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"teams",
|
|
||||||
"shared_links"
|
"shared_links"
|
||||||
],
|
],
|
||||||
"data_retention_in_years": 5
|
"data_retention_in_years": 5
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments"
|
"site_segments"
|
||||||
],
|
],
|
||||||
|
|
@ -129,7 +128,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments"
|
"site_segments"
|
||||||
],
|
],
|
||||||
|
|
@ -145,7 +143,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments"
|
"site_segments"
|
||||||
],
|
],
|
||||||
|
|
@ -161,7 +158,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments"
|
"site_segments"
|
||||||
],
|
],
|
||||||
|
|
@ -177,7 +173,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments"
|
"site_segments"
|
||||||
],
|
],
|
||||||
|
|
@ -193,7 +188,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments"
|
"site_segments"
|
||||||
],
|
],
|
||||||
|
|
@ -209,7 +203,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments"
|
"site_segments"
|
||||||
],
|
],
|
||||||
|
|
@ -225,7 +218,6 @@
|
||||||
"team_member_limit": 3,
|
"team_member_limit": 3,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments"
|
"site_segments"
|
||||||
],
|
],
|
||||||
|
|
@ -241,7 +233,6 @@
|
||||||
"team_member_limit": 10,
|
"team_member_limit": 10,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"props",
|
"props",
|
||||||
|
|
@ -261,7 +252,6 @@
|
||||||
"team_member_limit": 10,
|
"team_member_limit": 10,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"props",
|
"props",
|
||||||
|
|
@ -281,7 +271,6 @@
|
||||||
"team_member_limit": 10,
|
"team_member_limit": 10,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"props",
|
"props",
|
||||||
|
|
@ -301,7 +290,6 @@
|
||||||
"team_member_limit": 10,
|
"team_member_limit": 10,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"props",
|
"props",
|
||||||
|
|
@ -321,7 +309,6 @@
|
||||||
"team_member_limit": 10,
|
"team_member_limit": 10,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"props",
|
"props",
|
||||||
|
|
@ -341,7 +328,6 @@
|
||||||
"team_member_limit": 10,
|
"team_member_limit": 10,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"props",
|
"props",
|
||||||
|
|
@ -361,7 +347,6 @@
|
||||||
"team_member_limit": 10,
|
"team_member_limit": 10,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"props",
|
"props",
|
||||||
|
|
@ -381,7 +366,6 @@
|
||||||
"team_member_limit": 10,
|
"team_member_limit": 10,
|
||||||
"features": [
|
"features": [
|
||||||
"goals",
|
"goals",
|
||||||
"teams",
|
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"site_segments",
|
"site_segments",
|
||||||
"props",
|
"props",
|
||||||
|
|
|
||||||
|
|
@ -30,11 +30,6 @@ defmodule Plausible.Billing.FeatureTest do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "Plausible.Billing.Feature.Teams.check_availability/2 returns :ok when user is on an enterprise plan" do
|
|
||||||
team = new_user() |> subscribe_to_enterprise_plan() |> team_of()
|
|
||||||
assert :ok == Plausible.Billing.Feature.Teams.check_availability(team)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "Plausible.Billing.Feature.SharedLinks.check_availability/2 returns :ok when user is on an enterprise plan" do
|
test "Plausible.Billing.Feature.SharedLinks.check_availability/2 returns :ok when user is on an enterprise plan" do
|
||||||
team = new_user() |> subscribe_to_enterprise_plan() |> team_of()
|
team = new_user() |> subscribe_to_enterprise_plan() |> team_of()
|
||||||
assert :ok == Plausible.Billing.Feature.SharedLinks.check_availability(team)
|
assert :ok == Plausible.Billing.Feature.SharedLinks.check_availability(team)
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ defmodule Plausible.Billing.QuotaTest do
|
||||||
use Plausible.DataCase, async: true
|
use Plausible.DataCase, async: true
|
||||||
use Plausible
|
use Plausible
|
||||||
alias Plausible.Billing.{Quota, Plans}
|
alias Plausible.Billing.{Quota, Plans}
|
||||||
alias Plausible.Billing.Feature.{Goals, Props, SitesAPI, StatsAPI, Teams, SharedLinks}
|
alias Plausible.Billing.Feature.{Goals, Props, SitesAPI, StatsAPI, SharedLinks}
|
||||||
|
|
||||||
use Plausible.Teams.Test
|
use Plausible.Teams.Test
|
||||||
|
|
||||||
|
|
@ -575,24 +575,18 @@ defmodule Plausible.Billing.QuotaTest do
|
||||||
test "users with expired trials have no access to subscription features" do
|
test "users with expired trials have no access to subscription features" do
|
||||||
team = new_user(trial_expiry_date: ~D[2023-01-01]) |> team_of()
|
team = new_user(trial_expiry_date: ~D[2023-01-01]) |> team_of()
|
||||||
|
|
||||||
assert [Goals, Plausible.Billing.Feature.Teams, Plausible.Billing.Feature.SharedLinks] ==
|
assert [Goals, Plausible.Billing.Feature.SharedLinks] ==
|
||||||
Plausible.Teams.Billing.allowed_features_for(team)
|
Plausible.Teams.Billing.allowed_features_for(team)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "returns all grandfathered features when user is on an old plan" do
|
for {generation, plan_id} <- [{"v1", @v1_plan_id}, {"v2", @v2_plan_id}, {"v3", @v3_plan_id}] do
|
||||||
team_on_v1 = new_user() |> subscribe_to_plan(@v1_plan_id) |> team_of()
|
test "returns all grandfathered features when user is on a #{generation} plan" do
|
||||||
team_on_v2 = new_user() |> subscribe_to_plan(@v2_plan_id) |> team_of()
|
team = new_user() |> subscribe_to_plan(unquote(plan_id)) |> team_of()
|
||||||
team_on_v3 = new_user() |> subscribe_to_plan(@v3_plan_id) |> team_of()
|
|
||||||
|
|
||||||
assert [Goals, Props, StatsAPI, Teams, SharedLinks] ==
|
assert [Goals, Props, StatsAPI, SharedLinks] ==
|
||||||
Plausible.Teams.Billing.allowed_features_for(team_on_v1)
|
Plausible.Teams.Billing.allowed_features_for(team)
|
||||||
|
end
|
||||||
assert [Goals, Props, StatsAPI, Teams, SharedLinks] ==
|
|
||||||
Plausible.Teams.Billing.allowed_features_for(team_on_v2)
|
|
||||||
|
|
||||||
assert [Goals, Props, StatsAPI, Teams, SharedLinks] ==
|
|
||||||
Plausible.Teams.Billing.allowed_features_for(team_on_v3)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
test "returns features for a free_10k plan" do
|
test "returns features for a free_10k plan" do
|
||||||
|
|
@ -600,7 +594,7 @@ defmodule Plausible.Billing.QuotaTest do
|
||||||
subscribe_to_plan(user, "free_10k")
|
subscribe_to_plan(user, "free_10k")
|
||||||
team = team_of(user)
|
team = team_of(user)
|
||||||
|
|
||||||
assert [Goals, Props, StatsAPI, Teams, SharedLinks] ==
|
assert [Goals, Props, StatsAPI, SharedLinks] ==
|
||||||
Plausible.Teams.Billing.allowed_features_for(team)
|
Plausible.Teams.Billing.allowed_features_for(team)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -619,7 +613,6 @@ defmodule Plausible.Billing.QuotaTest do
|
||||||
assert [
|
assert [
|
||||||
Plausible.Billing.Feature.StatsAPI,
|
Plausible.Billing.Feature.StatsAPI,
|
||||||
Plausible.Billing.Feature.Funnels,
|
Plausible.Billing.Feature.Funnels,
|
||||||
Plausible.Billing.Feature.Teams,
|
|
||||||
Plausible.Billing.Feature.SharedLinks
|
Plausible.Billing.Feature.SharedLinks
|
||||||
] ==
|
] ==
|
||||||
Plausible.Teams.Billing.allowed_features_for(team)
|
Plausible.Teams.Billing.allowed_features_for(team)
|
||||||
|
|
@ -641,7 +634,7 @@ defmodule Plausible.Billing.QuotaTest do
|
||||||
|
|
||||||
team = team_of(user)
|
team = team_of(user)
|
||||||
|
|
||||||
assert [Goals, Props, StatsAPI, Teams, SharedLinks] ==
|
assert [Goals, Props, StatsAPI, SharedLinks] ==
|
||||||
Plausible.Teams.Billing.allowed_features_for(team)
|
Plausible.Teams.Billing.allowed_features_for(team)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -669,7 +662,6 @@ defmodule Plausible.Billing.QuotaTest do
|
||||||
|
|
||||||
assert [
|
assert [
|
||||||
Plausible.Billing.Feature.StatsAPI,
|
Plausible.Billing.Feature.StatsAPI,
|
||||||
Plausible.Billing.Feature.Teams,
|
|
||||||
Plausible.Billing.Feature.SharedLinks
|
Plausible.Billing.Feature.SharedLinks
|
||||||
] ==
|
] ==
|
||||||
Plausible.Teams.Billing.allowed_features_for(team)
|
Plausible.Teams.Billing.allowed_features_for(team)
|
||||||
|
|
@ -687,7 +679,6 @@ defmodule Plausible.Billing.QuotaTest do
|
||||||
assert [
|
assert [
|
||||||
Plausible.Billing.Feature.StatsAPI,
|
Plausible.Billing.Feature.StatsAPI,
|
||||||
Plausible.Billing.Feature.SitesAPI,
|
Plausible.Billing.Feature.SitesAPI,
|
||||||
Plausible.Billing.Feature.Teams,
|
|
||||||
Plausible.Billing.Feature.SharedLinks
|
Plausible.Billing.Feature.SharedLinks
|
||||||
] ==
|
] ==
|
||||||
Plausible.Teams.Billing.allowed_features_for(team)
|
Plausible.Teams.Billing.allowed_features_for(team)
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ defmodule PlausibleWeb.Components.BillingTest do
|
||||||
%{
|
%{
|
||||||
current_role: :owner,
|
current_role: :owner,
|
||||||
current_team: user |> subscribe_to_growth_plan() |> team_of(),
|
current_team: user |> subscribe_to_growth_plan() |> team_of(),
|
||||||
feature_mod: Plausible.Billing.Feature.Props
|
locked?: true
|
||||||
}
|
}
|
||||||
|> render_feature_gate()
|
|> render_feature_gate()
|
||||||
|
|
||||||
|
|
@ -28,7 +28,7 @@ defmodule PlausibleWeb.Components.BillingTest do
|
||||||
%{
|
%{
|
||||||
current_role: nil,
|
current_role: nil,
|
||||||
current_team: nil,
|
current_team: nil,
|
||||||
feature_mod: Plausible.Billing.Feature.Props
|
locked?: true
|
||||||
}
|
}
|
||||||
|> render_feature_gate()
|
|> render_feature_gate()
|
||||||
|
|
||||||
|
|
@ -43,7 +43,7 @@ defmodule PlausibleWeb.Components.BillingTest do
|
||||||
%{
|
%{
|
||||||
current_role: :owner,
|
current_role: :owner,
|
||||||
current_team: user |> subscribe_to_business_plan() |> team_of(),
|
current_team: user |> subscribe_to_business_plan() |> team_of(),
|
||||||
feature_mod: Plausible.Billing.Feature.Funnels
|
locked?: false
|
||||||
}
|
}
|
||||||
|> render_feature_gate()
|
|> render_feature_gate()
|
||||||
|
|
||||||
|
|
@ -58,7 +58,7 @@ defmodule PlausibleWeb.Components.BillingTest do
|
||||||
%{
|
%{
|
||||||
current_role: :owner,
|
current_role: :owner,
|
||||||
current_team: user |> subscribe_to_growth_plan() |> team_of(),
|
current_team: user |> subscribe_to_growth_plan() |> team_of(),
|
||||||
feature_mod: Plausible.Billing.Feature.Props
|
locked?: true
|
||||||
}
|
}
|
||||||
|> render_feature_gate()
|
|> render_feature_gate()
|
||||||
|
|
||||||
|
|
@ -70,7 +70,7 @@ defmodule PlausibleWeb.Components.BillingTest do
|
||||||
%{
|
%{
|
||||||
current_role: :billing,
|
current_role: :billing,
|
||||||
current_team: user |> subscribe_to_growth_plan() |> team_of(),
|
current_team: user |> subscribe_to_growth_plan() |> team_of(),
|
||||||
feature_mod: Plausible.Billing.Feature.Props
|
locked?: true
|
||||||
}
|
}
|
||||||
|> render_feature_gate()
|
|> render_feature_gate()
|
||||||
|
|
||||||
|
|
@ -85,7 +85,7 @@ defmodule PlausibleWeb.Components.BillingTest do
|
||||||
%{
|
%{
|
||||||
current_role: :editor,
|
current_role: :editor,
|
||||||
current_team: user |> subscribe_to_growth_plan() |> team_of(),
|
current_team: user |> subscribe_to_growth_plan() |> team_of(),
|
||||||
feature_mod: Plausible.Billing.Feature.Props
|
locked?: true
|
||||||
}
|
}
|
||||||
|> render_feature_gate()
|
|> render_feature_gate()
|
||||||
|
|
||||||
|
|
@ -94,10 +94,11 @@ defmodule PlausibleWeb.Components.BillingTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp render_feature_gate(assigns) do
|
defp render_feature_gate(assigns) do
|
||||||
rendered_to_string(~H"""
|
~H"""
|
||||||
<PlausibleWeb.Components.Billing.feature_gate {assigns}>
|
<PlausibleWeb.Components.Billing.feature_gate {assigns}>
|
||||||
<div>content...</div>
|
<div>content...</div>
|
||||||
</PlausibleWeb.Components.Billing.feature_gate>
|
</PlausibleWeb.Components.Billing.feature_gate>
|
||||||
""")
|
"""
|
||||||
|
|> rendered_to_string()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -263,7 +263,7 @@ defmodule PlausibleWeb.AdminControllerTest do
|
||||||
conn = get(conn, "/crm/billing/team/#{team.id}/current_plan")
|
conn = get(conn, "/crm/billing/team/#{team.id}/current_plan")
|
||||||
|
|
||||||
assert json_response(conn, 200) == %{
|
assert json_response(conn, 200) == %{
|
||||||
"features" => ["goals", "teams", "shared_links"],
|
"features" => ["goals", "shared_links"],
|
||||||
"monthly_pageview_limit" => 10_000_000,
|
"monthly_pageview_limit" => 10_000_000,
|
||||||
"site_limit" => 10,
|
"site_limit" => 10,
|
||||||
"team_member_limit" => 3
|
"team_member_limit" => 3
|
||||||
|
|
|
||||||
|
|
@ -1421,16 +1421,6 @@ defmodule PlausibleWeb.SettingsControllerTest do
|
||||||
assert text_of_element(html, ~s/[data-test="create-a-team-cta"]/) == "Create a Team"
|
assert text_of_element(html, ~s/[data-test="create-a-team-cta"]/) == "Create a Team"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "does not render the 'Create a Team' option if Teams feature is unavailable", %{
|
|
||||||
conn: conn,
|
|
||||||
user: user
|
|
||||||
} do
|
|
||||||
subscribe_to_starter_plan(user)
|
|
||||||
conn = get(conn, Routes.settings_path(conn, :preferences))
|
|
||||||
html = html_response(conn, 200)
|
|
||||||
refute element_exists?(html, ~s/[data-test="create-a-team-cta"]/)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "does not render the 'Create a Team' option if a team is already set up", %{
|
test "does not render the 'Create a Team' option if a team is already set up", %{
|
||||||
conn: conn,
|
conn: conn,
|
||||||
user: user
|
user: user
|
||||||
|
|
|
||||||
|
|
@ -699,6 +699,7 @@ defmodule PlausibleWeb.SiteControllerTest do
|
||||||
refute resp =~ "Team members automatically have access to this site."
|
refute resp =~ "Team members automatically have access to this site."
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@tag :ee_only
|
||||||
test "does not render team management notice if Teams feature unavailable", %{
|
test "does not render team management notice if Teams feature unavailable", %{
|
||||||
conn: conn,
|
conn: conn,
|
||||||
user: user
|
user: user
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,6 @@ defmodule PlausibleWeb.Live.CustomerSupport.TeamsTest do
|
||||||
"false",
|
"false",
|
||||||
"false",
|
"false",
|
||||||
"false",
|
"false",
|
||||||
"teams",
|
|
||||||
"false",
|
"false",
|
||||||
"shared_links",
|
"shared_links",
|
||||||
"false",
|
"false",
|
||||||
|
|
@ -150,7 +149,6 @@ defmodule PlausibleWeb.Live.CustomerSupport.TeamsTest do
|
||||||
%Plausible.Billing.EnterprisePlan{
|
%Plausible.Billing.EnterprisePlan{
|
||||||
billing_interval: :yearly,
|
billing_interval: :yearly,
|
||||||
features: [
|
features: [
|
||||||
Plausible.Billing.Feature.Teams,
|
|
||||||
Plausible.Billing.Feature.SharedLinks,
|
Plausible.Billing.Feature.SharedLinks,
|
||||||
Plausible.Billing.Feature.SitesAPI
|
Plausible.Billing.Feature.SitesAPI
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,21 @@ defmodule PlausibleWeb.Live.TeamSetupTest do
|
||||||
_ = render(lv)
|
_ = render(lv)
|
||||||
assert Repo.reload!(team).name == "Team Name 1"
|
assert Repo.reload!(team).name == "Team Name 1"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@tag :ee_only
|
||||||
|
test "blurs UI with an upgrade CTA if the subscription team member limit is 0", %{
|
||||||
|
conn: conn,
|
||||||
|
user: user
|
||||||
|
} do
|
||||||
|
subscribe_to_starter_plan(user)
|
||||||
|
|
||||||
|
{:ok, _lv, html} = live(conn, @url)
|
||||||
|
|
||||||
|
assert class_of_element(html, "#feature-gate-inner-block-container") =~
|
||||||
|
"pointer-events-none"
|
||||||
|
|
||||||
|
assert class_of_element(html, "#feature-gate-overlay") =~ "backdrop-blur-[6px]"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "/team/setup - full integration" do
|
describe "/team/setup - full integration" do
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@ defmodule PlausibleWeb.Plugins.API.Controllers.CapabilitiesTest do
|
||||||
"StatsAPI" => false,
|
"StatsAPI" => false,
|
||||||
"SitesAPI" => false,
|
"SitesAPI" => false,
|
||||||
"SiteSegments" => false,
|
"SiteSegments" => false,
|
||||||
"Teams" => false,
|
|
||||||
"SharedLinks" => false
|
"SharedLinks" => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -60,7 +59,6 @@ defmodule PlausibleWeb.Plugins.API.Controllers.CapabilitiesTest do
|
||||||
"StatsAPI" => false,
|
"StatsAPI" => false,
|
||||||
"SitesAPI" => false,
|
"SitesAPI" => false,
|
||||||
"SiteSegments" => false,
|
"SiteSegments" => false,
|
||||||
"Teams" => false,
|
|
||||||
"SharedLinks" => false
|
"SharedLinks" => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -90,7 +88,6 @@ defmodule PlausibleWeb.Plugins.API.Controllers.CapabilitiesTest do
|
||||||
"StatsAPI" => true,
|
"StatsAPI" => true,
|
||||||
"SitesAPI" => false,
|
"SitesAPI" => false,
|
||||||
"SiteSegments" => true,
|
"SiteSegments" => true,
|
||||||
"Teams" => true,
|
|
||||||
"SharedLinks" => true
|
"SharedLinks" => true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -122,7 +119,6 @@ defmodule PlausibleWeb.Plugins.API.Controllers.CapabilitiesTest do
|
||||||
"StatsAPI" => false,
|
"StatsAPI" => false,
|
||||||
"SitesAPI" => false,
|
"SitesAPI" => false,
|
||||||
"SiteSegments" => false,
|
"SiteSegments" => false,
|
||||||
"Teams" => true,
|
|
||||||
"SharedLinks" => true
|
"SharedLinks" => true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -157,7 +153,6 @@ defmodule PlausibleWeb.Plugins.API.Controllers.CapabilitiesTest do
|
||||||
"StatsAPI" => true,
|
"StatsAPI" => true,
|
||||||
"SitesAPI" => true,
|
"SitesAPI" => true,
|
||||||
"SiteSegments" => false,
|
"SiteSegments" => false,
|
||||||
"Teams" => true,
|
|
||||||
"SharedLinks" => true
|
"SharedLinks" => true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,9 @@ defmodule PlausibleWeb.DevSubscriptionController do
|
||||||
use PlausibleWeb, :controller
|
use PlausibleWeb, :controller
|
||||||
|
|
||||||
alias Plausible.Billing.DevSubscriptions
|
alias Plausible.Billing.DevSubscriptions
|
||||||
|
alias Plausible.Auth.User
|
||||||
|
alias Plausible.Teams.Team
|
||||||
|
alias Plausible.Teams
|
||||||
|
|
||||||
plug PlausibleWeb.RequireAccountPlug
|
plug PlausibleWeb.RequireAccountPlug
|
||||||
|
|
||||||
|
|
@ -18,7 +21,7 @@ defmodule PlausibleWeb.DevSubscriptionController do
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_form(conn, _params) do
|
def update_form(conn, _params) do
|
||||||
team = conn.assigns.current_team |> Plausible.Teams.with_subscription()
|
team = conn.assigns.current_team |> Teams.with_subscription()
|
||||||
|
|
||||||
if is_nil(team.subscription),
|
if is_nil(team.subscription),
|
||||||
do: raise("Can't render subscription update form without subscription")
|
do: raise("Can't render subscription update form without subscription")
|
||||||
|
|
@ -30,20 +33,25 @@ defmodule PlausibleWeb.DevSubscriptionController do
|
||||||
end
|
end
|
||||||
|
|
||||||
def cancel_form(conn, _params) do
|
def cancel_form(conn, _params) do
|
||||||
team = conn.assigns.current_team |> Plausible.Teams.with_subscription()
|
team = conn.assigns.current_team |> Teams.with_subscription()
|
||||||
|
|
||||||
if is_nil(team.subscription),
|
if is_nil(team.subscription),
|
||||||
do: raise("Can't render subscription cancel form without subscription")
|
do: raise("Can't render subscription cancel form without subscription")
|
||||||
|
|
||||||
render(conn, "cancel_dev_subscription.html",
|
render(conn, "cancel_dev_subscription.html",
|
||||||
back_link: Routes.settings_path(conn, :subscription),
|
back_link: Routes.settings_path(conn, :subscription),
|
||||||
enterprise_plan?: Plausible.Teams.Billing.enterprise_configured?(team)
|
enterprise_plan?: Teams.Billing.enterprise_configured?(team)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create(conn, %{"plan_id" => plan_id}) do
|
def create(conn, %{"plan_id" => plan_id}) do
|
||||||
team = conn.assigns.current_team
|
for_team =
|
||||||
DevSubscriptions.create_after_1s(team.id, plan_id)
|
case conn.assigns do
|
||||||
|
%{current_team: %Team{} = team} -> team
|
||||||
|
%{current_user: %User{} = user} -> Teams.force_create_my_team(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
DevSubscriptions.create_after_1s(for_team.id, plan_id)
|
||||||
redirect(conn, to: Routes.billing_path(PlausibleWeb.Endpoint, :upgrade_success))
|
redirect(conn, to: Routes.billing_path(PlausibleWeb.Endpoint, :upgrade_success))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue