Merge branch 'master' into stats-module

This commit is contained in:
Uku Taht 2021-08-04 16:11:40 +03:00 committed by GitHub
commit 7e78157c4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 70 additions and 30 deletions

View File

@ -15,6 +15,7 @@ All notable changes to this project will be documented in this file.
- Menu (with auto-complete) to add new and edit existing filters directly plausible/analytics#1089 - Menu (with auto-complete) to add new and edit existing filters directly plausible/analytics#1089
- Added `CLICKHOUSE_FLUSH_INTERVAL_MS` and `CLICKHOUSE_MAX_BUFFER_SIZE` configuration parameters plausible/analytics#1073 - Added `CLICKHOUSE_FLUSH_INTERVAL_MS` and `CLICKHOUSE_MAX_BUFFER_SIZE` configuration parameters plausible/analytics#1073
- Ability to invite users to sites with different roles plausible/analytics#1122 - Ability to invite users to sites with different roles plausible/analytics#1122
- Option to configure a custom name for the script file
### Fixed ### Fixed
- Fix weekly report time range plausible/analytics#951 - Fix weekly report time range plausible/analytics#951
@ -23,7 +24,7 @@ All notable changes to this project will be documented in this file.
- Crash when changing theme on a loaded dashboard plausible/analytics#1123 - Crash when changing theme on a loaded dashboard plausible/analytics#1123
- UI fix for details button overlapping content on mobile plausible/analytics#1114 - UI fix for details button overlapping content on mobile plausible/analytics#1114
- UI fix for the main graph on mobile overlapping its tick items on both axis - UI fix for the main graph on mobile overlapping its tick items on both axis
- UI fixes for text not showing properly in bars across multiple lines. This hides the totals on <768px and only shows the uniques and % to accommodate the goals text too. - UI fixes for text not showing properly in bars across multiple lines. This hides the totals on <768px and only shows the uniques and % to accommodate the goals text too. Larger screens still truncate as usual.
- Turn off autocomplete for name and password inputs in the _New shared link_ form. - Turn off autocomplete for name and password inputs in the _New shared link_ form.
### Removed ### Removed

View File

@ -59,13 +59,13 @@ export default class Conversions extends React.Component {
renderGoalText(goalName) { renderGoalText(goalName) {
if (this.props.query.period === 'realtime') { if (this.props.query.period === 'realtime') {
return <span className="block px-2 py-1.5 relative z-9 break-words dark:text-gray-200">{goalName}</span> return <span className="block px-2 py-1.5 relative z-9 md:truncate break-all dark:text-gray-200">{goalName}</span>
} else { } else {
const query = new URLSearchParams(window.location.search) const query = new URLSearchParams(window.location.search)
query.set('goal', goalName) query.set('goal', goalName)
return ( return (
<Link to={{pathname: window.location.pathname, search: query.toString()}} className="block px-2 py-1.5 hover:underline relative z-9 break-words dark:text-gray-200"> <Link to={{pathname: window.location.pathname, search: query.toString()}} className="block px-2 py-1.5 hover:underline relative z-9 break-all lg:truncate dark:text-gray-200">
{goalName} {goalName}
</Link> </Link>
) )

View File

@ -71,10 +71,10 @@ export default class PropertyBreakdown extends React.Component {
renderPropContent(value, query) { renderPropContent(value, query) {
return ( return (
<span className="flex px-2 py-1.5 group dark:text-gray-300 relative z-9 break-words"> <span className="flex px-2 py-1.5 group dark:text-gray-300 relative z-9 break-all">
<Link <Link
to={{pathname: window.location.pathname, search: query.toString()}} to={{pathname: window.location.pathname, search: query.toString()}}
className="hover:underline block" className="md:truncate hover:underline block"
> >
{ value.name } { value.name }
</Link> </Link>

View File

@ -43,8 +43,8 @@ export default class Browsers extends React.Component {
renderBrowserContent(browser, query) { renderBrowserContent(browser, query) {
return ( return (
<span className="flex px-2 py-1.5 dark:text-gray-300 relative z-9 break-words"> <span className="flex px-2 py-1.5 dark:text-gray-300 relative z-9 break-all">
<Link className="block hover:underline" to={{search: query.toString()}}> <Link className="md:truncate block hover:underline" to={{search: query.toString()}}>
{browser.name} {browser.name}
</Link> </Link>
</span> </span>

View File

@ -86,7 +86,7 @@ class ScreenSizes extends React.Component {
tooltip={EXPLANATION[size.name]} tooltip={EXPLANATION[size.name]}
className="flex px-2 py-1.5 dark:text-gray-300" className="flex px-2 py-1.5 dark:text-gray-300"
> >
<Link className="block hover:underline" to={{search: query.toString()}}> <Link className="md:truncate block hover:underline" to={{search: query.toString()}}>
{iconFor(size.name)} {size.name} {iconFor(size.name)} {size.name}
</Link> </Link>
</span> </span>

View File

@ -55,8 +55,8 @@ export default class OperatingSystems extends React.Component {
bg="bg-green-50 dark:gray-500 dark:bg-opacity-15" bg="bg-green-50 dark:gray-500 dark:bg-opacity-15"
maxWidthDeduction="6rem" maxWidthDeduction="6rem"
> >
<span className="flex px-2 py-1.5 dark:text-gray-300 relative z-9 break-words"> <span className="flex px-2 py-1.5 dark:text-gray-300 relative z-9 break-all">
<Link className="block hover:underline" to={{search: query.toString()}}> <Link className="md:truncate block hover:underline" to={{search: query.toString()}}>
{os.name} {os.name}
</Link> </Link>
</span> </span>

View File

@ -46,10 +46,10 @@ export default class EntryPages extends React.Component {
bg="bg-orange-50 dark:bg-gray-500 dark:bg-opacity-15" bg="bg-orange-50 dark:bg-gray-500 dark:bg-opacity-15"
maxWidthDeduction="4rem" maxWidthDeduction="4rem"
> >
<span className="flex px-2 py-1.5 group dark:text-gray-300 relative break-words z-9"> <span className="flex px-2 py-1.5 group dark:text-gray-300 relative break-all z-9">
<Link <Link
to={{pathname: window.location.pathname, search: query.toString()}} to={{pathname: window.location.pathname, search: query.toString()}}
className="block hover:underline" className="md:truncate block hover:underline"
> >
{page.name} {page.name}
</Link> </Link>

View File

@ -46,10 +46,10 @@ export default class ExitPages extends React.Component {
bg="bg-orange-50 dark:bg-gray-500 dark:bg-opacity-15" bg="bg-orange-50 dark:bg-gray-500 dark:bg-opacity-15"
maxWidthDeduction="4rem" maxWidthDeduction="4rem"
> >
<span className="flex px-2 py-1.5 group dark:text-gray-300 z-9 relative break-words"> <span className="flex px-2 py-1.5 group dark:text-gray-300 z-9 relative break-all">
<Link <Link
to={{pathname: window.location.pathname, search: query.toString()}} to={{pathname: window.location.pathname, search: query.toString()}}
className="block hover:underline" className="md:truncate block hover:underline"
> >
{page.name} {page.name}
</Link> </Link>

View File

@ -52,11 +52,11 @@ export default class Visits extends React.Component {
maxWidthDeduction="4rem" maxWidthDeduction="4rem"
> >
<span <span
className="flex px-2 py-1.5 group dark:text-gray-300 relative z-9 break-words" className="flex px-2 py-1.5 group dark:text-gray-300 relative z-9 break-all"
> >
<Link <Link
to={{pathname: window.location.pathname, search: query.toString()}} to={{pathname: window.location.pathname, search: query.toString()}}
className="block hover:underline" className="md:truncate block hover:underline"
> >
{page.name} {page.name}
</Link> </Link>

View File

@ -78,9 +78,9 @@ export default class Referrers extends React.Component {
bg="bg-blue-50 dark:bg-gray-500 dark:bg-opacity-15" bg="bg-blue-50 dark:bg-gray-500 dark:bg-opacity-15"
maxWidthDeduction="4rem" maxWidthDeduction="4rem"
> >
<span className="flex px-2 py-1.5 z-9 relative break-words group"> <span className="flex px-2 py-1.5 z-9 relative break-all group">
<LinkOption <LinkOption
className="block dark:text-gray-300" className="block md:truncate dark:text-gray-300"
to={{search: query.toString()}} to={{search: query.toString()}}
disabled={referrer.name === 'Direct / None'} disabled={referrer.name === 'Direct / None'}
> >

View File

@ -42,8 +42,8 @@ export default class SearchTerms extends React.Component {
bg="bg-blue-50 dark:bg-gray-500 dark:bg-opacity-15" bg="bg-blue-50 dark:bg-gray-500 dark:bg-opacity-15"
maxWidthDeduction="4rem" maxWidthDeduction="4rem"
> >
<span className="flex px-2 py-1.5 dark:text-gray-300 z-9 relative break-words"> <span className="flex px-2 py-1.5 dark:text-gray-300 z-9 relative break-all">
<span className="block"> <span className="md:truncate block">
{ term.name } { term.name }
</span> </span>
</span> </span>

View File

@ -53,9 +53,9 @@ class AllSources extends React.Component {
bg="bg-blue-50 dark:bg-gray-500 dark:bg-opacity-15" bg="bg-blue-50 dark:bg-gray-500 dark:bg-opacity-15"
maxWidthDeduction="4rem" maxWidthDeduction="4rem"
> >
<span className="flex px-2 py-1.5 dark:text-gray-300 relative z-9 break-words"> <span className="flex px-2 py-1.5 dark:text-gray-300 relative z-9 break-all">
<Link <Link
className="block hover:underline" className="md:truncate block hover:underline"
to={{search: query.toString()}} to={{search: query.toString()}}
> >
<img <img
@ -171,9 +171,10 @@ class UTMSources extends React.Component {
bg="bg-blue-50 dark:bg-gray-500 dark:bg-opacity-15" bg="bg-blue-50 dark:bg-gray-500 dark:bg-opacity-15"
maxWidthDeduction="4rem" maxWidthDeduction="4rem"
> >
<span className="flex px-2 py-1.5 dark:text-gray-300 relative z-9 break-words">
<span className="flex px-2 py-1.5 dark:text-gray-300 relative z-9 break-all">
<Link <Link
className="block hover:underline" className="md:truncate block hover:underline"
to={{search: query.toString()}} to={{search: query.toString()}}
> >
{ referrer.name } { referrer.name }

View File

@ -136,6 +136,10 @@ is_selfhost =
|> get_var_from_path_or_env("SELFHOST", "true") |> get_var_from_path_or_env("SELFHOST", "true")
|> String.to_existing_atom() |> String.to_existing_atom()
custom_script_name =
config_dir
|> get_var_from_path_or_env("CUSTOM_SCRIPT_NAME", "script")
{site_limit, ""} = {site_limit, ""} =
config_dir config_dir
|> get_var_from_path_or_env("SITE_LIMIT", "50") |> get_var_from_path_or_env("SITE_LIMIT", "50")
@ -171,7 +175,8 @@ config :plausible,
admin_user_ids: admin_user_ids, admin_user_ids: admin_user_ids,
site_limit: site_limit, site_limit: site_limit,
site_limit_exempt: site_limit_exempt, site_limit_exempt: site_limit_exempt,
is_selfhost: is_selfhost is_selfhost: is_selfhost,
custom_script_name: custom_script_name
config :plausible, :selfhost, config :plausible, :selfhost,
disable_authentication: disable_auth, disable_authentication: disable_auth,

View File

@ -2,7 +2,9 @@ defmodule PlausibleWeb.Tracker do
import Plug.Conn import Plug.Conn
use Agent use Agent
custom_script_name = Application.get_env(:plausible, :custom_script_name)
base_variants = ["hash", "outbound-links", "exclusions", "compat"] base_variants = ["hash", "outbound-links", "exclusions", "compat"]
base_filenames = ["plausible", custom_script_name]
# Generates Power Set of all variants # Generates Power Set of all variants
variants = variants =
@ -24,8 +26,8 @@ defmodule PlausibleWeb.Tracker do
String.split(x, ".") String.split(x, ".")
|> Combination.permutate() |> Combination.permutate()
|> Enum.map(fn p -> Enum.join(p, ".") end) |> Enum.map(fn p -> Enum.join(p, ".") end)
|> Enum.filter(fn permutation -> permutation != x end) |> Enum.map(fn v -> Enum.map(base_filenames, fn filename -> "#{filename}.#{v}.js" end) end)
|> Enum.map(fn v -> "plausible.#{v}.js" end) |> List.flatten()
if Enum.count(variants) > 0 do if Enum.count(variants) > 0 do
{"plausible.#{x}.js", variants} {"plausible.#{x}.js", variants}
@ -33,7 +35,7 @@ defmodule PlausibleWeb.Tracker do
end) end)
|> Enum.reject(fn x -> x == nil end) |> Enum.reject(fn x -> x == nil end)
|> Enum.into(%{}) |> Enum.into(%{})
|> Map.put("plausible.js", ["analytics.js"]) |> Map.put("plausible.js", ["analytics.js", "#{custom_script_name}.js"])
@templates files_available @templates files_available
@aliases aliases_available @aliases aliases_available

View File

@ -0,0 +1,9 @@
defmodule Plausible.Repo.Migrations.MakeInvitationEmailCaseInsensitive do
use Ecto.Migration
def change do
alter table(:invitations) do
modify :email, :citext, null: false
end
end
end

View File

@ -44,6 +44,28 @@ defmodule PlausibleWeb.SiteControllerTest do
assert html_response(conn, 200) =~ "<b>3</b> visitors in last 24h" assert html_response(conn, 200) =~ "<b>3</b> visitors in last 24h"
end end
test "shows invitations for user by email address", %{conn: conn, user: user} do
site = insert(:site)
insert(:invitation, email: user.email, site_id: site.id, inviter: build(:user))
conn = get(conn, "/sites")
assert html_response(conn, 200) =~ site.domain
end
test "invitations are case insensitive", %{conn: conn, user: user} do
site = insert(:site)
insert(:invitation,
email: String.upcase(user.email),
site_id: site.id,
inviter: build(:user)
)
conn = get(conn, "/sites")
assert html_response(conn, 200) =~ site.domain
end
test "paginates sites", %{conn: conn, user: user} do test "paginates sites", %{conn: conn, user: user} do
insert(:site, members: [user], domain: "test-site1.com") insert(:site, members: [user], domain: "test-site1.com")
insert(:site, members: [user], domain: "test-site2.com") insert(:site, members: [user], domain: "test-site2.com")