mirror of
https://github.com/plausible/analytics.git
synced 2024-12-24 01:54:34 +03:00
commit
1ec4dca33f
@ -15,6 +15,7 @@ All notable changes to this project will be documented in this file.
|
|||||||
- Display domain's favicon on the home page
|
- Display domain's favicon on the home page
|
||||||
- Ignore consecutive pageviews on same pathname plausible/analytics#417
|
- Ignore consecutive pageviews on same pathname plausible/analytics#417
|
||||||
- Validate domain format on site creation plausible/analytics#427
|
- Validate domain format on site creation plausible/analytics#427
|
||||||
|
- Improve settings UX and design plausible/analytics#412
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Do not error when activating an already activated account plausible/analytics#370
|
- Do not error when activating an already activated account plausible/analytics#370
|
||||||
|
@ -7,15 +7,7 @@
|
|||||||
@import "tooltip.css";
|
@import "tooltip.css";
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
@apply inline-block bg-indigo-600 text-white text-center font-bold tracking-wide py-2 px-5 rounded no-underline;
|
@apply bg-indigo-600 border border-transparent rounded-md py-2 px-4 inline-flex justify-center text-sm leading-5 font-medium text-white transition hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500;
|
||||||
}
|
|
||||||
|
|
||||||
.button:hover {
|
|
||||||
@apply shadow;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button:focus {
|
|
||||||
@apply outline-none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-outline {
|
.button-outline {
|
||||||
|
@ -3,6 +3,7 @@ import "flatpickr/dist/flatpickr.min.css"
|
|||||||
import "./polyfills/closest"
|
import "./polyfills/closest"
|
||||||
import 'abortcontroller-polyfill/dist/polyfill-patch-fetch'
|
import 'abortcontroller-polyfill/dist/polyfill-patch-fetch'
|
||||||
import "phoenix_html"
|
import "phoenix_html"
|
||||||
|
import 'alpinejs'
|
||||||
|
|
||||||
const triggers = document.querySelectorAll('[data-dropdown-trigger]')
|
const triggers = document.querySelectorAll('[data-dropdown-trigger]')
|
||||||
|
|
||||||
@ -33,14 +34,6 @@ if (triggers.length > 0) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const flash = document.getElementById('flash')
|
|
||||||
|
|
||||||
if (flash) {
|
|
||||||
setTimeout(function() {
|
|
||||||
flash.style.display = 'none'
|
|
||||||
}, 2500)
|
|
||||||
}
|
|
||||||
|
|
||||||
const registerForm = document.getElementById('register-form')
|
const registerForm = document.getElementById('register-form')
|
||||||
|
|
||||||
if (registerForm) {
|
if (registerForm) {
|
||||||
|
@ -186,7 +186,7 @@ class DatePicker extends React.Component {
|
|||||||
if (this.state.mode === 'menu') {
|
if (this.state.mode === 'menu') {
|
||||||
return (
|
return (
|
||||||
<div className="absolute mt-2 rounded shadow-md z-10" style={{width: '235px', right: '-14px'}}>
|
<div className="absolute mt-2 rounded shadow-md z-10" style={{width: '235px', right: '-14px'}}>
|
||||||
<div className="rounded bg-white shadow-xs font-medium text-gray-800">
|
<div className="rounded bg-white ring-1 ring-black ring-opacity-5 font-medium text-gray-800">
|
||||||
<div className="py-1">
|
<div className="py-1">
|
||||||
{ this.renderLink('day', 'Today') }
|
{ this.renderLink('day', 'Today') }
|
||||||
{ this.renderLink('realtime', 'Realtime') }
|
{ this.renderLink('realtime', 'Realtime') }
|
||||||
|
@ -88,7 +88,7 @@ export default class SiteSwitcher extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const hoverClass = this.props.loggedIn ? 'hover:text-gray-500 focus:border-blue-300 focus:shadow-outline-blue ' : 'cursor-default'
|
const hoverClass = this.props.loggedIn ? 'hover:text-gray-500 focus:border-blue-300 focus:ring ' : 'cursor-default'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative inline-block text-left z-10 mr-8">
|
<div className="relative inline-block text-left z-10 mr-8">
|
||||||
@ -109,7 +109,7 @@ export default class SiteSwitcher extends React.Component {
|
|||||||
leaveTo="opacity-0 scale-95"
|
leaveTo="opacity-0 scale-95"
|
||||||
>
|
>
|
||||||
<div className="origin-top-left absolute left-0 mt-2 w-64 rounded-md shadow-lg" ref={node => this.dropDownNode = node} >
|
<div className="origin-top-left absolute left-0 mt-2 w-64 rounded-md shadow-lg" ref={node => this.dropDownNode = node} >
|
||||||
<div className="rounded-md bg-white shadow-xs">
|
<div className="rounded-md bg-white ring-1 ring-black ring-opacity-5">
|
||||||
{ this.renderDropdown() }
|
{ this.renderDropdown() }
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -106,7 +106,7 @@ class SourcesModal extends React.Component {
|
|||||||
} else if (this.state.moreResultsAvailable) {
|
} else if (this.state.moreResultsAvailable) {
|
||||||
return (
|
return (
|
||||||
<div className="w-full text-center my-4">
|
<div className="w-full text-center my-4">
|
||||||
<button onClick={this.loadMore.bind(this)} type="button" className="inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:border-indigo-700 focus:shadow-outline-indigo active:bg-indigo-700 transition ease-in-out duration-150">
|
<button onClick={this.loadMore.bind(this)} type="button" className="inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:border-indigo-700 focus:ring active:bg-indigo-700 transition ease-in-out duration-150">
|
||||||
Load more
|
Load more
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
1295
assets/package-lock.json
generated
1295
assets/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -9,9 +9,11 @@
|
|||||||
"@babel/core": "^7.11.1",
|
"@babel/core": "^7.11.1",
|
||||||
"@babel/preset-env": "^7.11.0",
|
"@babel/preset-env": "^7.11.0",
|
||||||
"@babel/preset-react": "^7.10.4",
|
"@babel/preset-react": "^7.10.4",
|
||||||
"@fullhuman/postcss-purgecss": "^2.3.0",
|
"@tailwindcss/aspect-ratio": "^0.2.0",
|
||||||
"@tailwindcss/ui": "^0.1.4",
|
"@tailwindcss/forms": "^0.2.1",
|
||||||
|
"@tailwindcss/typography": "^0.3.1",
|
||||||
"abortcontroller-polyfill": "^1.5.0",
|
"abortcontroller-polyfill": "^1.5.0",
|
||||||
|
"alpinejs": "^2.7.3",
|
||||||
"autoprefixer": "^9.8.6",
|
"autoprefixer": "^9.8.6",
|
||||||
"babel-loader": "^8.1.0",
|
"babel-loader": "^8.1.0",
|
||||||
"chart.js": "^2.9.3",
|
"chart.js": "^2.9.3",
|
||||||
@ -22,17 +24,20 @@
|
|||||||
"optimize-css-assets-webpack-plugin": "^5.0.3",
|
"optimize-css-assets-webpack-plugin": "^5.0.3",
|
||||||
"phoenix": "file:../deps/phoenix",
|
"phoenix": "file:../deps/phoenix",
|
||||||
"phoenix_html": "file:../deps/phoenix_html",
|
"phoenix_html": "file:../deps/phoenix_html",
|
||||||
"postcss-loader": "^3.0.0",
|
"postcss": "^7.0.35",
|
||||||
|
"postcss-loader": "^4.0.4",
|
||||||
"react": "^16.13.1",
|
"react": "^16.13.1",
|
||||||
"react-dom": "^16.13.1",
|
"react-dom": "^16.13.1",
|
||||||
"react-flatpickr": "^3.10.5",
|
"react-flatpickr": "^3.10.5",
|
||||||
"react-flip-move": "^3.0.4",
|
"react-flip-move": "^3.0.4",
|
||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
"react-transition-group": "^4.4.1",
|
"react-transition-group": "^4.4.1",
|
||||||
"tailwindcss": "^1.6.2",
|
"tailwindcss": "^2.0.1-compat",
|
||||||
"uglifyjs-webpack-plugin": "^2.2.0",
|
|
||||||
"url-search-params-polyfill": "^8.0.0",
|
"url-search-params-polyfill": "^8.0.0",
|
||||||
"webpack": "4.39.2",
|
"webpack": "4.39.2",
|
||||||
"webpack-cli": "^3.3.12"
|
"webpack-cli": "^3.3.12"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"terser-webpack-plugin": "^4.2.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,6 @@
|
|||||||
const purgecss = require('@fullhuman/postcss-purgecss')({
|
|
||||||
content: [
|
|
||||||
'./js/**/*.js',
|
|
||||||
'../lib/plausible_web/templates/**/*.html.eex',
|
|
||||||
],
|
|
||||||
defaultExtractor: content => content.match(/[\w-/.:]+(?<!:)/g) || [],
|
|
||||||
whitelistPatterns: [/flatpickr\S+/],
|
|
||||||
whitelistPatternsChildren: [/flatpickr\S+/]
|
|
||||||
})
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
plugins: [
|
plugins: {
|
||||||
require('tailwindcss'),
|
tailwindcss: {},
|
||||||
require('autoprefixer'),
|
autoprefixer: {},
|
||||||
...process.env.NODE_ENV === 'production'
|
}
|
||||||
? [purgecss]
|
|
||||||
: []
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,20 @@
|
|||||||
|
const colors = require('tailwindcss/colors')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
purge: [
|
||||||
|
'./js/**/*.js',
|
||||||
|
'../lib/plausible_web/templates/**/*.html.eex',
|
||||||
|
],
|
||||||
|
darkMode: false,
|
||||||
theme: {
|
theme: {
|
||||||
container: {
|
container: {
|
||||||
center: true,
|
center: true,
|
||||||
padding: '1rem',
|
padding: '1rem',
|
||||||
},
|
},
|
||||||
extend: {
|
extend: {
|
||||||
|
colors: {
|
||||||
|
orange: colors.orange,
|
||||||
|
},
|
||||||
spacing: {
|
spacing: {
|
||||||
'44': '11rem'
|
'44': '11rem'
|
||||||
},
|
},
|
||||||
@ -17,8 +27,9 @@ module.exports = {
|
|||||||
textColor: ['responsive', 'hover', 'focus', 'group-hover'],
|
textColor: ['responsive', 'hover', 'focus', 'group-hover'],
|
||||||
display: ['responsive', 'hover', 'focus', 'group-hover']
|
display: ['responsive', 'hover', 'focus', 'group-hover']
|
||||||
},
|
},
|
||||||
corePlugins: {},
|
|
||||||
plugins: [
|
plugins: [
|
||||||
require('@tailwindcss/ui')
|
require('@tailwindcss/forms'),
|
||||||
],
|
require('@tailwindcss/typography'),
|
||||||
|
require('@tailwindcss/aspect-ratio'),
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const glob = require('glob');
|
const glob = require('glob');
|
||||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||||
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
|
const TerserPlugin = require('terser-webpack-plugin');
|
||||||
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
|
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
|
||||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||||
const DefinePlugin = require('webpack').DefinePlugin;
|
const DefinePlugin = require('webpack').DefinePlugin;
|
||||||
@ -9,7 +9,7 @@ const DefinePlugin = require('webpack').DefinePlugin;
|
|||||||
module.exports = (env, options) => ({
|
module.exports = (env, options) => ({
|
||||||
optimization: {
|
optimization: {
|
||||||
minimizer: [
|
minimizer: [
|
||||||
new UglifyJsPlugin({ cache: true, parallel: true, sourceMap: false }),
|
new TerserPlugin(),
|
||||||
new OptimizeCSSAssetsPlugin({})
|
new OptimizeCSSAssetsPlugin({})
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -65,7 +65,7 @@ defmodule PlausibleWeb.SiteController do
|
|||||||
{:ok, _} ->
|
{:ok, _} ->
|
||||||
conn
|
conn
|
||||||
|> put_flash(:success, "Goal created succesfully")
|
|> put_flash(:success, "Goal created succesfully")
|
||||||
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings")
|
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings/goals")
|
||||||
|
|
||||||
{:error, :goal, changeset, _} ->
|
{:error, :goal, changeset, _} ->
|
||||||
conn
|
conn
|
||||||
@ -83,35 +83,100 @@ defmodule PlausibleWeb.SiteController do
|
|||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_flash(:success, "Goal deleted succesfully")
|
|> put_flash(:success, "Goal deleted succesfully")
|
||||||
|> redirect(to: "/#{URI.encode_www_form(website)}/settings")
|
|> redirect(to: "/#{URI.encode_www_form(website)}/settings/goals")
|
||||||
end
|
end
|
||||||
|
|
||||||
def settings(conn, %{"website" => website}) do
|
def settings(conn, %{"website" => website}) do
|
||||||
site =
|
redirect(conn, to: "/#{URI.encode_www_form(website)}/settings/general")
|
||||||
Sites.get_for_user!(conn.assigns[:current_user].id, website)
|
end
|
||||||
|
|
||||||
|
def settings_general(conn, %{"website" => website}) do
|
||||||
|
site = Sites.get_for_user!(conn.assigns[:current_user].id, website)
|
||||||
|
|> Repo.preload(:custom_domain)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> assign(:skip_plausible_tracking, true)
|
||||||
|
|> render("settings_general.html",
|
||||||
|
site: site,
|
||||||
|
changeset: Plausible.Site.changeset(site, %{}),
|
||||||
|
layout: {PlausibleWeb.LayoutView, "site_settings.html"}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def settings_visibility(conn, %{"website" => website}) do
|
||||||
|
site = Sites.get_for_user!(conn.assigns[:current_user].id, website)
|
||||||
|
shared_links = Repo.all(from l in Plausible.Site.SharedLink, where: l.site_id == ^site.id)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> assign(:skip_plausible_tracking, true)
|
||||||
|
|> render("settings_visibility.html",
|
||||||
|
site: site,
|
||||||
|
shared_links: shared_links,
|
||||||
|
layout: {PlausibleWeb.LayoutView, "site_settings.html"}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def settings_goals(conn, %{"website" => website}) do
|
||||||
|
site = Sites.get_for_user!(conn.assigns[:current_user].id, website)
|
||||||
|
goals = Goals.for_site(site.domain)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> assign(:skip_plausible_tracking, true)
|
||||||
|
|> render("settings_goals.html",
|
||||||
|
site: site,
|
||||||
|
goals: goals,
|
||||||
|
layout: {PlausibleWeb.LayoutView, "site_settings.html"}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def settings_search_console(conn, %{"website" => website}) do
|
||||||
|
site = Sites.get_for_user!(conn.assigns[:current_user].id, website)
|
||||||
|> Repo.preload(:google_auth)
|
|> Repo.preload(:google_auth)
|
||||||
|> Repo.preload(:custom_domain)
|
|
||||||
|
|
||||||
search_console_domains =
|
search_console_domains =
|
||||||
if site.google_auth do
|
if site.google_auth do
|
||||||
Plausible.Google.Api.fetch_verified_properties(site.google_auth)
|
Plausible.Google.Api.fetch_verified_properties(site.google_auth)
|
||||||
end
|
end
|
||||||
|
|
||||||
weekly_report = Repo.get_by(Plausible.Site.WeeklyReport, site_id: site.id)
|
conn
|
||||||
monthly_report = Repo.get_by(Plausible.Site.MonthlyReport, site_id: site.id)
|
|> assign(:skip_plausible_tracking, true)
|
||||||
goals = Goals.for_site(site.domain)
|
|> render("settings_search_console.html",
|
||||||
shared_links = Repo.all(from l in Plausible.Site.SharedLink, where: l.site_id == ^site.id)
|
site: site,
|
||||||
|
search_console_domains: search_console_domains,
|
||||||
|
layout: {PlausibleWeb.LayoutView, "site_settings.html"}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def settings_email_reports(conn, %{"website" => website}) do
|
||||||
|
site = Sites.get_for_user!(conn.assigns[:current_user].id, website)
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> assign(:skip_plausible_tracking, true)
|
|> assign(:skip_plausible_tracking, true)
|
||||||
|> render("settings.html",
|
|> render("settings_email_reports.html",
|
||||||
site: site,
|
site: site,
|
||||||
weekly_report: weekly_report,
|
weekly_report: Repo.get_by(Plausible.Site.WeeklyReport, site_id: site.id),
|
||||||
monthly_report: monthly_report,
|
monthly_report: Repo.get_by(Plausible.Site.MonthlyReport, site_id: site.id),
|
||||||
search_console_domains: search_console_domains,
|
layout: {PlausibleWeb.LayoutView, "site_settings.html"}
|
||||||
goals: goals,
|
)
|
||||||
shared_links: shared_links,
|
end
|
||||||
changeset: Plausible.Site.changeset(site, %{})
|
|
||||||
|
def settings_custom_domain(conn, %{"website" => website}) do
|
||||||
|
site = Sites.get_for_user!(conn.assigns[:current_user].id, website)
|
||||||
|
|> Repo.preload(:custom_domain)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> assign(:skip_plausible_tracking, true)
|
||||||
|
|> render("settings_custom_domain.html", site: site, layout: {PlausibleWeb.LayoutView, "site_settings.html"})
|
||||||
|
end
|
||||||
|
|
||||||
|
def settings_danger_zone(conn, %{"website" => website}) do
|
||||||
|
site = Sites.get_for_user!(conn.assigns[:current_user].id, website)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> assign(:skip_plausible_tracking, true)
|
||||||
|
|> render("settings_danger_zone.html",
|
||||||
|
site: site,
|
||||||
|
layout: {PlausibleWeb.LayoutView, "site_settings.html"}
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -125,7 +190,7 @@ defmodule PlausibleWeb.SiteController do
|
|||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_flash(:success, "Google integration saved succesfully")
|
|> put_flash(:success, "Google integration saved succesfully")
|
||||||
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings#google-auth")
|
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings/search-console")
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete_google_auth(conn, %{"website" => website}) do
|
def delete_google_auth(conn, %{"website" => website}) do
|
||||||
@ -136,8 +201,8 @@ defmodule PlausibleWeb.SiteController do
|
|||||||
Repo.delete!(site.google_auth)
|
Repo.delete!(site.google_auth)
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_flash(:success, "Google account unlinked succesfully")
|
|> put_flash(:success, "Google account unlinked from Plausible")
|
||||||
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings#google-auth")
|
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings/search-console")
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_settings(conn, %{"website" => website, "site" => site_params}) do
|
def update_settings(conn, %{"website" => website, "site" => site_params}) do
|
||||||
@ -151,11 +216,11 @@ defmodule PlausibleWeb.SiteController do
|
|||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_session(site_session_key, nil)
|
|> put_session(site_session_key, nil)
|
||||||
|> put_flash(:success, "Site settings saved succesfully")
|
|> put_flash(:success, "Your site settings have been saved")
|
||||||
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings")
|
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings/general")
|
||||||
|
|
||||||
{:error, changeset} ->
|
{:error, changeset} ->
|
||||||
render("settings.html", site: site, changeset: changeset)
|
render("settings_general.html", site: site, changeset: changeset)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -165,7 +230,7 @@ defmodule PlausibleWeb.SiteController do
|
|||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_flash(:success, "#{site.domain} stats will be reset in a few minutes")
|
|> put_flash(:success, "#{site.domain} stats will be reset in a few minutes")
|
||||||
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings")
|
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings/danger-zone")
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete_site(conn, %{"website" => website}) do
|
def delete_site(conn, %{"website" => website}) do
|
||||||
@ -194,8 +259,8 @@ defmodule PlausibleWeb.SiteController do
|
|||||||
|> Repo.update!()
|
|> Repo.update!()
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_flash(:success, "Congrats! Stats for #{site.domain} are now public.")
|
|> put_flash(:success, "Stats for #{site.domain} are now public.")
|
||||||
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings")
|
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings/visibility")
|
||||||
end
|
end
|
||||||
|
|
||||||
def make_private(conn, %{"website" => website}) do
|
def make_private(conn, %{"website" => website}) do
|
||||||
@ -206,7 +271,7 @@ defmodule PlausibleWeb.SiteController do
|
|||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_flash(:success, "Stats for #{site.domain} are now private.")
|
|> put_flash(:success, "Stats for #{site.domain} are now private.")
|
||||||
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings")
|
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings/visibility")
|
||||||
end
|
end
|
||||||
|
|
||||||
def enable_weekly_report(conn, %{"website" => website}) do
|
def enable_weekly_report(conn, %{"website" => website}) do
|
||||||
@ -219,8 +284,8 @@ defmodule PlausibleWeb.SiteController do
|
|||||||
|> Repo.insert!()
|
|> Repo.insert!()
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_flash(:success, "Success! You will receive an email report every Monday going forward")
|
|> put_flash(:success, "You will receive an email report every Monday going forward")
|
||||||
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings#email-reports")
|
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings/email-reports")
|
||||||
end
|
end
|
||||||
|
|
||||||
def disable_weekly_report(conn, %{"website" => website}) do
|
def disable_weekly_report(conn, %{"website" => website}) do
|
||||||
@ -228,8 +293,8 @@ defmodule PlausibleWeb.SiteController do
|
|||||||
Repo.delete_all(from wr in Plausible.Site.WeeklyReport, where: wr.site_id == ^site.id)
|
Repo.delete_all(from wr in Plausible.Site.WeeklyReport, where: wr.site_id == ^site.id)
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_flash(:success, "Success! You will not receive weekly email reports going forward")
|
|> put_flash(:success, "You will not receive weekly email reports going forward")
|
||||||
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings#email-reports")
|
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings/email-reports")
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_weekly_report_recipient(conn, %{"website" => website, "recipient" => recipient}) do
|
def add_weekly_report_recipient(conn, %{"website" => website, "recipient" => recipient}) do
|
||||||
@ -240,8 +305,8 @@ defmodule PlausibleWeb.SiteController do
|
|||||||
|> Repo.update!()
|
|> Repo.update!()
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_flash(:success, "Succesfully added #{recipient} as a recipient for the weekly report")
|
|> put_flash(:success, "Added #{recipient} as a recipient for the weekly report")
|
||||||
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings#email-reports")
|
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings/email-reports")
|
||||||
end
|
end
|
||||||
|
|
||||||
def remove_weekly_report_recipient(conn, %{"website" => website, "recipient" => recipient}) do
|
def remove_weekly_report_recipient(conn, %{"website" => website, "recipient" => recipient}) do
|
||||||
@ -254,9 +319,9 @@ defmodule PlausibleWeb.SiteController do
|
|||||||
conn
|
conn
|
||||||
|> put_flash(
|
|> put_flash(
|
||||||
:success,
|
:success,
|
||||||
"Succesfully removed #{recipient} as a recipient for the weekly report"
|
"Removed #{recipient} as a recipient for the weekly report"
|
||||||
)
|
)
|
||||||
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings#email-reports")
|
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings/email-reports")
|
||||||
end
|
end
|
||||||
|
|
||||||
def enable_monthly_report(conn, %{"website" => website}) do
|
def enable_monthly_report(conn, %{"website" => website}) do
|
||||||
@ -269,8 +334,8 @@ defmodule PlausibleWeb.SiteController do
|
|||||||
|> Repo.insert!()
|
|> Repo.insert!()
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_flash(:success, "Success! You will receive an email report every month going forward")
|
|> put_flash(:success, "You will receive an email report every month going forward")
|
||||||
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings#email-reports")
|
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings/email-reports")
|
||||||
end
|
end
|
||||||
|
|
||||||
def disable_monthly_report(conn, %{"website" => website}) do
|
def disable_monthly_report(conn, %{"website" => website}) do
|
||||||
@ -278,8 +343,8 @@ defmodule PlausibleWeb.SiteController do
|
|||||||
Repo.delete_all(from mr in Plausible.Site.MonthlyReport, where: mr.site_id == ^site.id)
|
Repo.delete_all(from mr in Plausible.Site.MonthlyReport, where: mr.site_id == ^site.id)
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_flash(:success, "Success! You will not receive monthly email reports going forward")
|
|> put_flash(:success, "You will not receive monthly email reports going forward")
|
||||||
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings#email-reports")
|
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings/email-reports")
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_monthly_report_recipient(conn, %{"website" => website, "recipient" => recipient}) do
|
def add_monthly_report_recipient(conn, %{"website" => website, "recipient" => recipient}) do
|
||||||
@ -290,8 +355,8 @@ defmodule PlausibleWeb.SiteController do
|
|||||||
|> Repo.update!()
|
|> Repo.update!()
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_flash(:success, "Succesfully added #{recipient} as a recipient for the monthly report")
|
|> put_flash(:success, "Added #{recipient} as a recipient for the monthly report")
|
||||||
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings#email-reports")
|
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings/email-reports")
|
||||||
end
|
end
|
||||||
|
|
||||||
def remove_monthly_report_recipient(conn, %{"website" => website, "recipient" => recipient}) do
|
def remove_monthly_report_recipient(conn, %{"website" => website, "recipient" => recipient}) do
|
||||||
@ -304,9 +369,9 @@ defmodule PlausibleWeb.SiteController do
|
|||||||
conn
|
conn
|
||||||
|> put_flash(
|
|> put_flash(
|
||||||
:success,
|
:success,
|
||||||
"Succesfully removed #{recipient} as a recipient for the monthly report"
|
"Removed #{recipient} as a recipient for the monthly report"
|
||||||
)
|
)
|
||||||
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings#email-reports")
|
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings/email-reports")
|
||||||
end
|
end
|
||||||
|
|
||||||
def new_shared_link(conn, %{"website" => website}) do
|
def new_shared_link(conn, %{"website" => website}) do
|
||||||
@ -336,7 +401,7 @@ defmodule PlausibleWeb.SiteController do
|
|||||||
|
|
||||||
case Repo.insert(changes) do
|
case Repo.insert(changes) do
|
||||||
{:ok, _created} ->
|
{:ok, _created} ->
|
||||||
redirect(conn, to: "/#{URI.encode_www_form(site.domain)}/settings#visibility")
|
redirect(conn, to: "/#{URI.encode_www_form(site.domain)}/settings/visibility")
|
||||||
|
|
||||||
{:error, changeset} ->
|
{:error, changeset} ->
|
||||||
conn
|
conn
|
||||||
@ -355,7 +420,7 @@ defmodule PlausibleWeb.SiteController do
|
|||||||
Repo.get_by(Plausible.Site.SharedLink, slug: slug)
|
Repo.get_by(Plausible.Site.SharedLink, slug: slug)
|
||||||
|> Repo.delete!()
|
|> Repo.delete!()
|
||||||
|
|
||||||
redirect(conn, to: "/#{URI.encode_www_form(site.domain)}/settings#visibility")
|
redirect(conn, to: "/#{URI.encode_www_form(site.domain)}/settings/visibility")
|
||||||
end
|
end
|
||||||
|
|
||||||
def new_custom_domain(conn, %{"website" => website}) do
|
def new_custom_domain(conn, %{"website" => website}) do
|
||||||
@ -424,7 +489,7 @@ defmodule PlausibleWeb.SiteController do
|
|||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_flash(:success, "Custom domain deleted succesfully")
|
|> put_flash(:success, "Custom domain deleted succesfully")
|
||||||
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings")
|
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings/custom-domain")
|
||||||
end
|
end
|
||||||
|
|
||||||
defp insert_site(user_id, params) do
|
defp insert_site(user_id, params) do
|
||||||
|
@ -145,7 +145,13 @@ defmodule PlausibleWeb.Router do
|
|||||||
|
|
||||||
get "/:website/snippet", SiteController, :add_snippet
|
get "/:website/snippet", SiteController, :add_snippet
|
||||||
get "/:website/settings", SiteController, :settings
|
get "/:website/settings", SiteController, :settings
|
||||||
get "/:website/goals", SiteController, :goals
|
get "/:website/settings/general", SiteController, :settings_general
|
||||||
|
get "/:website/settings/visibility", SiteController, :settings_visibility
|
||||||
|
get "/:website/settings/goals", SiteController, :settings_goals
|
||||||
|
get "/:website/settings/search-console", SiteController, :settings_search_console
|
||||||
|
get "/:website/settings/email-reports", SiteController, :settings_email_reports
|
||||||
|
get "/:website/settings/custom-domain", SiteController, :settings_custom_domain
|
||||||
|
get "/:website/settings/danger-zone", SiteController, :settings_danger_zone
|
||||||
get "/:website/goals/new", SiteController, :new_goal
|
get "/:website/goals/new", SiteController, :new_goal
|
||||||
post "/:website/goals", SiteController, :create_goal
|
post "/:website/goals", SiteController, :create_goal
|
||||||
delete "/:website/goals/:id", SiteController, :delete_goal
|
delete "/:website/goals/:id", SiteController, :delete_goal
|
||||||
|
@ -80,11 +80,11 @@
|
|||||||
<%= cond do %>
|
<%= cond do %>
|
||||||
<% @subscription && @subscription.status in ["active", "past_due", "paused"] && @subscription.cancel_url -> %>
|
<% @subscription && @subscription.status in ["active", "past_due", "paused"] && @subscription.cancel_url -> %>
|
||||||
<div class="mt-8">
|
<div class="mt-8">
|
||||||
<%= link("Cancel my subscription", to: @subscription.cancel_url, class: "inline-block mt-4 px-4 py-2 border border-gray-300 text-sm leading-5 font-medium rounded-md text-red-700 bg-white hover:text-red-500 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue active:text-red-800 active:bg-gray-50 transition ease-in-out duration-150") %>
|
<%= link("Cancel my subscription", to: @subscription.cancel_url, class: "inline-block mt-4 px-4 py-2 border border-gray-300 text-sm leading-5 font-medium rounded-md text-red-700 bg-white hover:text-red-500 focus:outline-none focus:border-blue-300 focus:ring active:text-red-800 active:bg-gray-50 transition ease-in-out duration-150") %>
|
||||||
</div>
|
</div>
|
||||||
<% true -> %>
|
<% true -> %>
|
||||||
<div class="mt-8">
|
<div class="mt-8">
|
||||||
<%= link("Upgrade", to: "/billing/upgrade", class: "inline-block px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:border-indigo-700 focus:shadow-outline-indigo active:bg-indigo-700 transition ease-in-out duration-150") %>
|
<%= link("Upgrade", to: "/billing/upgrade", class: "inline-block px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:border-indigo-700 focus:ring active:bg-indigo-700 transition ease-in-out duration-150") %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
@ -123,6 +123,6 @@
|
|||||||
<span class="button bg-gray-300 mt-6 hover:shadow-none">Delete my account</span>
|
<span class="button bg-gray-300 mt-6 hover:shadow-none">Delete my account</span>
|
||||||
<p class="text-gray-600 text-sm mt-2">Your account cannot be deleted because you have an active subscription. If you want to delete your account, please cancel your subscription first.</p>
|
<p class="text-gray-600 text-sm mt-2">Your account cannot be deleted because you have an active subscription. If you want to delete your account, please cancel your subscription first.</p>
|
||||||
<% else %>
|
<% else %>
|
||||||
<%= link("Delete my account", to: "/me", class: "inline-block mt-4 px-4 py-2 border border-gray-300 text-sm leading-5 font-medium rounded-md text-red-700 bg-white hover:text-red-500 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue active:text-red-800 active:bg-gray-50 transition ease-in-out duration-150", method: "delete", data: [confirm: "Deleting your account cannot be reversed. Are you sure?"]) %>
|
<%= link("Delete my account", to: "/me", class: "inline-block mt-4 px-4 py-2 border border-gray-300 text-sm leading-5 font-medium rounded-md text-red-700 bg-white hover:text-red-500 focus:outline-none focus:border-blue-300 focus:ring active:text-red-800 active:bg-gray-50 transition ease-in-out duration-150", method: "delete", data: [confirm: "Deleting your account cannot be reversed. Are you sure?"]) %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
@ -20,10 +20,10 @@
|
|||||||
<div class="pt-8"></div>
|
<div class="pt-8"></div>
|
||||||
|
|
||||||
<span class="relative z-0 inline-flex shadow-sm w-full">
|
<span class="relative z-0 inline-flex shadow-sm w-full">
|
||||||
<button type="button" @click="billingCycle = 'monthly'" :class="{'bg-indigo-600 text-white border-indigo-600': billingCycle === 'monthly', 'bg-white text-gray-700 hover:text-gray-500 border-gray-300': billingCycle === 'yearly'}" class="relative w-full text-center px-4 py-2 rounded-l-md border text-sm leading-5 font-medium focus:outline-none focus:border-blue-300 focus:shadow-outline-blue transition ease-in-out duration-150">
|
<button type="button" @click="billingCycle = 'monthly'" :class="{'bg-indigo-600 text-white border-indigo-600': billingCycle === 'monthly', 'bg-white text-gray-700 hover:text-gray-500 border-gray-300': billingCycle === 'yearly'}" class="relative w-full text-center px-4 py-2 rounded-l-md border text-sm leading-5 font-medium focus:outline-none focus:border-blue-300 focus:ring transition ease-in-out duration-150">
|
||||||
Monthly billing
|
Monthly billing
|
||||||
</button>
|
</button>
|
||||||
<button type="button" @click="billingCycle = 'yearly'" :class="{'bg-indigo-600 text-white border-indigo-600': billingCycle === 'yearly', 'bg-white text-gray-700 hover:text-gray-500 border-gray-300': billingCycle === 'monthly'}" class="-ml-px relative w-full text-center px-4 py-2 rounded-r-md border text-sm leading-5 font-medium focus:outline-none focus:border-blue-300 focus:shadow-outline-blue transition ease-in-out duration-150">
|
<button type="button" @click="billingCycle = 'yearly'" :class="{'bg-indigo-600 text-white border-indigo-600': billingCycle === 'yearly', 'bg-white text-gray-700 hover:text-gray-500 border-gray-300': billingCycle === 'monthly'}" class="-ml-px relative w-full text-center px-4 py-2 rounded-r-md border text-sm leading-5 font-medium focus:outline-none focus:border-blue-300 focus:ring transition ease-in-out duration-150">
|
||||||
Yearly billing
|
Yearly billing
|
||||||
<span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium leading-4 bg-yellow-100 text-yellow-800">
|
<span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium leading-4 bg-yellow-100 text-yellow-800">
|
||||||
-33%
|
-33%
|
||||||
@ -105,7 +105,7 @@
|
|||||||
|
|
||||||
<div class="text-right mt-6">
|
<div class="text-right mt-6">
|
||||||
<span class="inline-flex rounded-md shadow-sm">
|
<span class="inline-flex rounded-md shadow-sm">
|
||||||
<a x-show="window.plans[billingCycle][volume].product_id !== '<%= @subscription.paddle_plan_id %>'" style="display: none;" :href="'/billing/change-plan/preview/' + window.plans[billingCycle][volume].product_id" class="inline-flex items-center px-4 py-2 border border-transparent text-sm leading-5 font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:border-indigo-700 focus:shadow-outline-indigo active:bg-indigo-700 transition ease-in-out duration-150">
|
<a x-show="window.plans[billingCycle][volume].product_id !== '<%= @subscription.paddle_plan_id %>'" style="display: none;" :href="'/billing/change-plan/preview/' + window.plans[billingCycle][volume].product_id" class="inline-flex items-center px-4 py-2 border border-transparent text-sm leading-5 font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:border-indigo-700 focus:ring active:bg-indigo-700 transition ease-in-out duration-150">
|
||||||
<svg fill="currentColor" viewBox="0 0 20 20" class="w-4 h-4 inline mr-2"><path d="M10 12a2 2 0 100-4 2 2 0 000 4z"></path><path fill-rule="evenodd" d="M.458 10C1.732 5.943 5.522 3 10 3s8.268 2.943 9.542 7c-1.274 4.057-5.064 7-9.542 7S1.732 14.057.458 10zM14 10a4 4 0 11-8 0 4 4 0 018 0z" clip-rule="evenodd"></path></svg>
|
<svg fill="currentColor" viewBox="0 0 20 20" class="w-4 h-4 inline mr-2"><path d="M10 12a2 2 0 100-4 2 2 0 000 4z"></path><path fill-rule="evenodd" d="M.458 10C1.732 5.943 5.522 3 10 3s8.268 2.943 9.542 7c-1.274 4.057-5.064 7-9.542 7S1.732 14.057.458 10zM14 10a4 4 0 11-8 0 4 4 0 018 0z" clip-rule="evenodd"></path></svg>
|
||||||
Preview changes
|
Preview changes
|
||||||
</a>
|
</a>
|
||||||
@ -124,5 +124,4 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript" src="https://cdn.paddle.com/paddle/paddle.js"></script>
|
<script type="text/javascript" src="https://cdn.paddle.com/paddle/paddle.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.0.1/dist/alpine.js" defer></script>
|
|
||||||
<script>Paddle.Setup({vendor: 49430})</script>
|
<script>Paddle.Setup({vendor: 49430})</script>
|
||||||
|
@ -66,12 +66,12 @@
|
|||||||
|
|
||||||
<div class="flex items-center justify-between mt-10">
|
<div class="flex items-center justify-between mt-10">
|
||||||
<span class="flex rounded-md shadow-sm">
|
<span class="flex rounded-md shadow-sm">
|
||||||
<a href="/billing/change-plan" type="button" class="inline-flex items-center px-4 py-2 border border-gray-300 text-sm leading-5 font-medium rounded-md text-gray-700 bg-white hover:text-gray-500 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue active:text-gray-800 active:bg-gray-50 transition ease-in-out duration-150">
|
<a href="/billing/change-plan" type="button" class="inline-flex items-center px-4 py-2 border border-gray-300 text-sm leading-5 font-medium rounded-md text-gray-700 bg-white hover:text-gray-500 focus:outline-none focus:border-blue-300 focus:ring active:text-gray-800 active:bg-gray-50 transition ease-in-out duration-150">
|
||||||
Back
|
Back
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
<span class="flex space-betwee rounded-md shadow-sm">
|
<span class="flex space-betwee rounded-md shadow-sm">
|
||||||
<%= button("Confirm plan change", to: "/billing/change-plan/#{@preview_info["plan_id"]}", method: :post, class: "inline-flex items-center px-4 py-2 border border-transparent text-sm leading-5 font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:border-indigo-700 focus:shadow-outline-indigo active:bg-indigo-700 transition ease-in-out duration-150") %>
|
<%= button("Confirm plan change", to: "/billing/change-plan/#{@preview_info["plan_id"]}", method: :post, class: "inline-flex items-center px-4 py-2 border border-transparent text-sm leading-5 font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:border-indigo-700 focus:ring active:bg-indigo-700 transition ease-in-out duration-150") %>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -82,5 +82,4 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript" src="https://cdn.paddle.com/paddle/paddle.js"></script>
|
<script type="text/javascript" src="https://cdn.paddle.com/paddle/paddle.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.0.1/dist/alpine.js" defer></script>
|
|
||||||
<script>Paddle.Setup({vendor: 49430})</script>
|
<script>Paddle.Setup({vendor: 49430})</script>
|
||||||
|
@ -16,10 +16,10 @@
|
|||||||
<div class="pt-2"></div>
|
<div class="pt-2"></div>
|
||||||
|
|
||||||
<span class="relative z-0 inline-flex shadow-sm w-full">
|
<span class="relative z-0 inline-flex shadow-sm w-full">
|
||||||
<button type="button" @click="billingCycle = 'monthly'" :class="{'bg-indigo-600 text-white border-indigo-600': billingCycle === 'monthly', 'bg-white text-gray-700 hover:text-gray-500 border-gray-300': billingCycle === 'yearly'}" class="relative w-full text-center px-4 py-2 rounded-l-md border text-sm leading-5 font-medium focus:outline-none focus:border-blue-300 focus:shadow-outline-blue transition ease-in-out duration-150">
|
<button type="button" @click="billingCycle = 'monthly'" :class="{'bg-indigo-600 text-white border-indigo-600': billingCycle === 'monthly', 'bg-white text-gray-700 hover:text-gray-500 border-gray-300': billingCycle === 'yearly'}" class="relative w-full text-center px-4 py-2 rounded-l-md border text-sm leading-5 font-medium focus:outline-none focus:border-blue-300 focus:ring transition ease-in-out duration-150">
|
||||||
Monthly billing
|
Monthly billing
|
||||||
</button>
|
</button>
|
||||||
<button type="button" @click="billingCycle = 'yearly'" :class="{'bg-indigo-600 text-white border-indigo-600': billingCycle === 'yearly', 'bg-white text-gray-700 hover:text-gray-500 border-gray-300': billingCycle === 'monthly'}" class="-ml-px relative w-full text-center px-4 py-2 rounded-r-md border text-sm leading-5 font-medium focus:outline-none focus:border-blue-300 focus:shadow-outline-blue transition ease-in-out duration-150">
|
<button type="button" @click="billingCycle = 'yearly'" :class="{'bg-indigo-600 text-white border-indigo-600': billingCycle === 'yearly', 'bg-white text-gray-700 hover:text-gray-500 border-gray-300': billingCycle === 'monthly'}" class="-ml-px relative w-full text-center px-4 py-2 rounded-r-md border text-sm leading-5 font-medium focus:outline-none focus:border-blue-300 focus:ring transition ease-in-out duration-150">
|
||||||
Yearly billing
|
Yearly billing
|
||||||
<span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium leading-4 bg-yellow-100 text-yellow-800">
|
<span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium leading-4 bg-yellow-100 text-yellow-800">
|
||||||
-33%
|
-33%
|
||||||
@ -102,7 +102,7 @@
|
|||||||
<div class="text-right mt-6">
|
<div class="text-right mt-6">
|
||||||
<div class="mb-4 text-sm font-medium">Due today: <b x-text="window.plans[billingCycle][planSize].due_now">$6</b></div>
|
<div class="mb-4 text-sm font-medium">Due today: <b x-text="window.plans[billingCycle][planSize].due_now">$6</b></div>
|
||||||
<span class="inline-flex rounded-md shadow-sm">
|
<span class="inline-flex rounded-md shadow-sm">
|
||||||
<button type="button" data-theme="none" :data-product="window.plans[billingCycle][planSize].product_id" data-email="<%= @conn.assigns[:current_user].email %>" data-disable-logout="true" data-passthrough="<%= @conn.assigns[:current_user].id %>" data-success="/billing/upgrade-success" class="paddle_button inline-flex items-center px-4 py-2 border border-transparent text-sm leading-5 font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:border-indigo-700 focus:shadow-outline-indigo active:bg-indigo-700 transition ease-in-out duration-150">
|
<button type="button" data-theme="none" :data-product="window.plans[billingCycle][planSize].product_id" data-email="<%= @conn.assigns[:current_user].email %>" data-disable-logout="true" data-passthrough="<%= @conn.assigns[:current_user].id %>" data-success="/billing/upgrade-success" class="paddle_button inline-flex items-center px-4 py-2 border border-transparent text-sm leading-5 font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:border-indigo-700 focus:ring active:bg-indigo-700 transition ease-in-out duration-150">
|
||||||
<svg fill="currentColor" viewBox="0 0 20 20" class="w-4 h-4 inline mr-2"><path fill-rule="evenodd" d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z" clip-rule="evenodd"></path></svg>
|
<svg fill="currentColor" viewBox="0 0 20 20" class="w-4 h-4 inline mr-2"><path fill-rule="evenodd" d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z" clip-rule="evenodd"></path></svg>
|
||||||
Pay securely via Paddle
|
Pay securely via Paddle
|
||||||
</button>
|
</button>
|
||||||
@ -128,5 +128,4 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript" src="https://cdn.paddle.com/paddle/paddle.js"></script>
|
<script type="text/javascript" src="https://cdn.paddle.com/paddle/paddle.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.0.1/dist/alpine.js" defer></script>
|
|
||||||
<script>Paddle.Setup({vendor: 49430})</script>
|
<script>Paddle.Setup({vendor: 49430})</script>
|
||||||
|
34
lib/plausible_web/templates/layout/_flash.html.eex
Normal file
34
lib/plausible_web/templates/layout/_flash.html.eex
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<%= if get_flash(@conn, :success) do %>
|
||||||
|
<div class="z-50 fixed inset-0 flex items-end justify-center px-4 py-6 pointer-events-none sm:p-6 sm:items-start sm:justify-end">
|
||||||
|
<div x-data="{ show: true }" x-show="show" x-init="setTimeout(() => show = false, 4000)" x-transition:enter="transform ease-out duration-300 transition" x-transition:enter-start="translate-y-2 opacity-0 sm:translate-y-0 sm:translate-x-2" x-transition:enter-end="translate-y-0 opacity-100 sm:translate-x-0" x-transition:leave="transition ease-in duration-100" x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0" class="max-w-sm w-full bg-white shadow-lg rounded-lg pointer-events-auto">
|
||||||
|
<div class="rounded-lg ring-1 ring-black ring-opacity-5 overflow-hidden">
|
||||||
|
<div class="p-4">
|
||||||
|
<div class="flex items-start">
|
||||||
|
<div class="flex-shrink-0">
|
||||||
|
<!-- Heroicon name: check-circle -->
|
||||||
|
<svg class="h-6 w-6 text-green-400" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div class="ml-3 w-0 flex-1 pt-0.5">
|
||||||
|
<p class="text-sm leading-5 font-medium text-gray-900">
|
||||||
|
<%= get_flash(@conn, :success_title) || "Success!" %>
|
||||||
|
</p>
|
||||||
|
<p class="mt-1 text-sm leading-5 text-gray-500">
|
||||||
|
<%= get_flash(@conn, :success) %>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="ml-4 flex-shrink-0 flex">
|
||||||
|
<button class="inline-flex text-gray-400 focus:outline-none focus:text-gray-500 transition ease-in-out duration-150" @click="show = false">
|
||||||
|
<!-- Heroicon name: x -->
|
||||||
|
<svg class="h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
|
||||||
|
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
@ -1,4 +1,4 @@
|
|||||||
<div class="bg-gray-800">
|
<div class="bg-gray-800 mt-12">
|
||||||
<div class="container py-12 px-4 sm:px-6 lg:py-16 lg:px-8">
|
<div class="container py-12 px-4 sm:px-6 lg:py-16 lg:px-8">
|
||||||
<div class="xl:grid xl:grid-cols-3 xl:gap-8">
|
<div class="xl:grid xl:grid-cols-3 xl:gap-8">
|
||||||
<div class="my-8 xl:my-0">
|
<div class="my-8 xl:my-0">
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
<%= if is_current_tab(@conn, @this_tab) do %>
|
||||||
|
<a href="/<%= URI.encode_www_form(@site.domain) %>/settings/<%= @this_tab %>" class="flex items-center px-3 py-2 text-sm leading-5 font-medium text-gray-900 rounded-md bg-gray-100 hover:text-gray-900 hover:bg-gray-100 focus:outline-none focus:bg-gray-200 transition ease-in-out duration-150 <%= if @this_tab != "general", do: "mt-1" %>"><%= @text %></a>
|
||||||
|
<% else %>
|
||||||
|
<a href="/<%= URI.encode_www_form(@site.domain) %>/settings/<%= @this_tab %>" class="flex items-center px-3 py-2 text-sm leading-5 font-medium text-gray-600 rounded-md hover:text-gray-900 hover:bg-gray-50 focus:outline-none focus:text-gray-900 focus:bg-gray-50 transition ease-in-out duration-150 <%= if @this_tab != "general", do: "mt-1" %>"><%= @text %></a>
|
||||||
|
<% end %>
|
@ -51,7 +51,7 @@
|
|||||||
<ul class="flex" x-show="!document.cookie.includes('logged_in=true')">
|
<ul class="flex" x-show="!document.cookie.includes('logged_in=true')">
|
||||||
<li>
|
<li>
|
||||||
<div class="inline-flex rounded shadow ml-6">
|
<div class="inline-flex rounded shadow ml-6">
|
||||||
<a href="/" class="inline-flex items-center justify-center px-5 py-2 border border-transparent text-base leading-6 font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:shadow-outline transition duration-150 ease-in-out">My Sites</a>
|
<a href="/" class="inline-flex items-center justify-center px-5 py-2 border border-transparent text-base leading-6 font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:ring transition duration-150 ease-in-out">My Sites</a>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -70,7 +70,7 @@
|
|||||||
<a href="/login" class="font-medium text-gray-500 hover:text-gray-900 focus:outline-none focus:text-gray-900 transition duration-150 ease-in-out">Login</a>
|
<a href="/login" class="font-medium text-gray-500 hover:text-gray-900 focus:outline-none focus:text-gray-900 transition duration-150 ease-in-out">Login</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="inline-flex rounded shadow ml-6">
|
<div class="inline-flex rounded shadow ml-6">
|
||||||
<a href="/register" class="inline-flex items-center justify-center px-5 py-2 border border-transparent text-base leading-6 font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:shadow-outline transition duration-150 ease-in-out">Sign up</a>
|
<a href="/register" class="inline-flex items-center justify-center px-5 py-2 border border-transparent text-base leading-6 font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:ring transition duration-150 ease-in-out">Sign up</a>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -80,11 +80,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<%= if get_flash(@conn, :success) do %>
|
<%= render("_flash.html", assigns) %>
|
||||||
<div id="flash" class="text-center bg-green-500 text-green-100 text-sm font-bold px-4 absolute w-full transition overflow-hidden" style="top: 91px" role="alert">
|
|
||||||
<p class="py-3 "><%= get_flash(@conn, :success) %></p>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<%= if get_flash(@conn, :error) do %>
|
<%= if get_flash(@conn, :error) do %>
|
||||||
<div id="flash" class="text-center bg-red-dark-500 text-red-100 text-sm font-bold px-4 absolute w-full transition overflow-hidden" style="top: 91px" role="alert">
|
<div id="flash" class="text-center bg-red-dark-500 text-red-100 text-sm font-bold px-4 absolute w-full transition overflow-hidden" style="top: 91px" role="alert">
|
||||||
@ -106,7 +102,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="order-3 mt-2 flex-shrink-0 w-full sm:order-2 sm:mt-0 sm:w-auto">
|
<div class="order-3 mt-2 flex-shrink-0 w-full sm:order-2 sm:mt-0 sm:w-auto">
|
||||||
<div class="rounded-md shadow-sm">
|
<div class="rounded-md shadow-sm">
|
||||||
<%= link("Update billing info", to: @conn.assigns[:current_user].subscription.update_url, class: "flex items-center justify-center px-4 py-2 border border-transparent text-sm leading-5 font-medium rounded-md text-gray-600 bg-white hover:text-gray-500 focus:outline-none focus:shadow-outline transition ease-in-out duration-150") %>
|
<%= link("Update billing info", to: @conn.assigns[:current_user].subscription.update_url, class: "flex items-center justify-center px-4 py-2 border border-transparent text-sm leading-5 font-medium rounded-md text-gray-600 bg-white hover:text-gray-500 focus:outline-none focus:ring transition ease-in-out duration-150") %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -128,7 +124,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="order-3 mt-2 flex-shrink-0 w-full sm:order-2 sm:mt-0 sm:w-auto">
|
<div class="order-3 mt-2 flex-shrink-0 w-full sm:order-2 sm:mt-0 sm:w-auto">
|
||||||
<div class="rounded-md shadow-sm">
|
<div class="rounded-md shadow-sm">
|
||||||
<%= link("Update billing info", to: @conn.assigns[:current_user].subscription.update_url, class: "flex items-center justify-center px-4 py-2 border border-transparent text-sm leading-5 font-medium rounded-md text-gray-600 bg-white hover:text-gray-500 focus:outline-none focus:shadow-outline transition ease-in-out duration-150") %>
|
<%= link("Update billing info", to: @conn.assigns[:current_user].subscription.update_url, class: "flex items-center justify-center px-4 py-2 border border-transparent text-sm leading-5 font-medium rounded-md text-gray-600 bg-white hover:text-gray-500 focus:outline-none focus:ring transition ease-in-out duration-150") %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -137,7 +133,7 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<main class="flex-1">
|
<main class="flex-1">
|
||||||
<%= render @view_module, @view_template, assigns %>
|
<%= Map.get(assigns, :inner_layout) || render @view_module, @view_template, assigns %>
|
||||||
</main>
|
</main>
|
||||||
<%= render("_footer.html", assigns) %>
|
<%= render("_footer.html", assigns) %>
|
||||||
<script type="text/javascript" src="<%= Routes.static_path(@conn, "/js/app.js") %>"></script>
|
<script type="text/javascript" src="<%= Routes.static_path(@conn, "/js/app.js") %>"></script>
|
||||||
|
26
lib/plausible_web/templates/layout/site_settings.html.eex
Normal file
26
lib/plausible_web/templates/layout/site_settings.html.eex
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<%= render_layout "app.html", assigns do %>
|
||||||
|
<div class="container pt-6">
|
||||||
|
<%= link("← Back to stats", to: "/#{URI.encode_www_form(@site.domain)}", class: "text-sm text-indigo-600 font-bold") %>
|
||||||
|
<div class="pb-5 border-b border-gray-200">
|
||||||
|
<h2 class="text-2xl font-bold leading-7 text-gray-900 sm:text-3xl sm:leading-9 sm:truncate">
|
||||||
|
Settings for <%= @site.domain %>
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<div class="lg:grid lg:grid-cols-12 lg:gap-x-5 lg:mt-4">
|
||||||
|
<div class="py-4 g:py-0 lg:col-span-3">
|
||||||
|
<%= form_for @conn, "/sites/#{URI.encode_www_form(@site.domain)}/monthly-report/recipients", [class: "lg:hidden"], fn f -> %>
|
||||||
|
<%= select f, :tab, settings_tabs(), class: "mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md", onchange: "location.href = location.href.replace(/[^\/\/]*$/, event.target.value)", selected: List.last(@conn.path_info) %>
|
||||||
|
<% end %>
|
||||||
|
<div class="hidden lg:block">
|
||||||
|
<%= for [key: key, value: val] <- settings_tabs() do %>
|
||||||
|
<%= render("_settings_tab.html", this_tab: val, text: key, site: @site, conn: @conn) %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="space-y-6 lg:col-span-9 lg:mt-4">
|
||||||
|
<%= render @view_module, @view_template, assigns %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
@ -18,7 +18,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<%= link("Back to settings →", class: "button mt-4 w-full", to: "/#{URI.encode_www_form(@site.domain)}/settings#custom-domain") %>
|
<%= link("Back to settings →", class: "button mt-4 w-full", to: "/#{URI.encode_www_form(@site.domain)}/settings/custom-domain") %>
|
||||||
<p class="mt-4 text-gray-600 text-sm">
|
<p class="mt-4 text-gray-600 text-sm">
|
||||||
Problems? <%= link("Get help via email", to: "mailto:support@plausible.io", class: "text-indigo-800 underline") %>
|
Problems? <%= link("Get help via email", to: "mailto:support@plausible.io", class: "text-indigo-800 underline") %>
|
||||||
</p>
|
</p>
|
||||||
|
@ -1,258 +0,0 @@
|
|||||||
<div class="pt-12"></div>
|
|
||||||
<div class="max-w-xl mx-auto flex justify-between">
|
|
||||||
<a href="/<%= URI.encode_www_form(@site.domain) %>"><h1 class="text-2xl font-black">Settings for <%= @site.domain %></h1></a>
|
|
||||||
</div>
|
|
||||||
<div class="max-w-xl mx-auto bg-white shadow-md rounded rounded-t-none border-t-2 border-indigo-100 px-8 pt-6 pb-8 mt-6">
|
|
||||||
<div class="flex items-center justify-between">
|
|
||||||
<h2 class="text-xl font-black">General</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="my-4 border-b border-gray-200"></div>
|
|
||||||
|
|
||||||
<%= form_for @changeset, "/#{URI.encode_www_form(@site.domain)}/settings", [class: "max-w-xs"], fn f -> %>
|
|
||||||
<div class="my-4">
|
|
||||||
<%= label f, :domain, class: "block text-gray-700 text-sm font-bold mb-2" %>
|
|
||||||
<%= text_input f, :domain, class: "transition bg-gray-100 appearance-none border border-transparent rounded w-full p-2 text-gray-700 leading-normal appearance-none focus:outline-none focus:border-gray-300 ", disabled: "disabled" %>
|
|
||||||
<%= error_tag f, :domain %>
|
|
||||||
</div>
|
|
||||||
<div class="my-4">
|
|
||||||
<%= label f, :timezone, "Reporting Timezone", class: "block text-gray-700 text-sm font-bold mb-2" %>
|
|
||||||
<div class="inline-block relative w-full">
|
|
||||||
<%= select f, :timezone, Plausible.Timezones.options(), class: "block appearance-none w-full bg-gray-100 text-gray-700 cursor-pointer hover:border-gray-500 p-2 pr-8 rounded leading-normal focus:outline-none" %>
|
|
||||||
<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-pink-500">
|
|
||||||
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z"/></svg>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<%= submit "Save changes", class: "button mt-4" %>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="max-w-xl mx-auto bg-white shadow-md rounded rounded-t-none border-t-2 border-indigo-100 px-8 pt-6 pb-8 mt-10" id="visibility">
|
|
||||||
<h2 class="text-xl font-black">Visibility</h2>
|
|
||||||
|
|
||||||
<div class="my-4 border-b border-gray-300"></div>
|
|
||||||
<%= if @site.public do %>
|
|
||||||
Stats for <%= @site.domain %> are currently <b>public</b>. Anyone with the following link can view the stats:
|
|
||||||
<div class="relative text-sm mt-4">
|
|
||||||
<input type="text" id="public-link" value="<%= plausible_url() <> "/" <> URI.encode_www_form(@site.domain)%>" class="transition bg-gray-100 appearance-none border border-transparent rounded w-full p-2 pr-16 text-gray-700 appearance-none focus:outline-none" />
|
|
||||||
<a onclick="var input = document.getElementById('public-link'); input.focus(); input.select(); document.execCommand('copy');" href="javascript:void(0)" class="absolute right-0 text-indigo-700 font-bold p-2">
|
|
||||||
<svg class="feather-sm" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<%= button("Make stats private", to: "/sites/#{URI.encode_www_form(@site.domain)}/make-private", method: "POST", class: "button mt-8") %>
|
|
||||||
<% else %>
|
|
||||||
<div class="text-gray-700">
|
|
||||||
Stats for <%= @site.domain %> are currently <b>private</b>. You are the only person who can see them.
|
|
||||||
If you choose to make your stats public, anyone with the link will be able to view them.
|
|
||||||
</div>
|
|
||||||
<%= button("Make stats public", to: "/sites/#{URI.encode_www_form(@site.domain)}/make-public", method: "POST", class: "button mt-8") %>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<div class="mt-12">
|
|
||||||
<h2 class="text-xl font-black">Shared links</h2>
|
|
||||||
|
|
||||||
<div class="my-4 border-b border-gray-300"></div>
|
|
||||||
|
|
||||||
<div class="my-4">
|
|
||||||
You can share your stats privately by generating a shared link. The links are impossible to guess and
|
|
||||||
you can add password protection for extra security.
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<%= for link <- @shared_links do %>
|
|
||||||
<div class="flex relative w-full mt-2 text-sm">
|
|
||||||
<input type="text" id="<%= link.slug %>" readonly="readonly" value="<%= shared_link_dest(link) %>" class="transition bg-gray-100 appearance-none border border-transparent rounded rounded-r-none w-full p-2 text-gray-700 appearance-none focus:outline-none focus:border-gray-300" />
|
|
||||||
<button onclick="var input = document.getElementById('<%= link.slug %>'); input.focus(); input.select(); document.execCommand('copy');" href="javascript:void(0)" class="py-2 px-4 bg-gray-100 text-indigo-800 rounded-none border-r border-gray-300">
|
|
||||||
<svg class="feather-sm" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>
|
|
||||||
</button>
|
|
||||||
<%= button(to: "/sites/#{URI.encode_www_form(@site.domain)}/shared-links/#{link.slug}", method: :delete, class: "py-2 px-4 bg-gray-100 text-red-600 rounded-l-none", data: [confirm: "Are you sure you want to delete this shared link? The stats will not be accessible with this link anymore."]) do %>
|
|
||||||
<svg class="feather feather-sm" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path><line x1="10" y1="11" x2="10" y2="17"></line><line x1="14" y1="11" x2="14" y2="17"></line></svg>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<%= link("+ New link", to: "/sites/#{URI.encode_www_form(@site.domain)}/shared-links/new", class: "button mt-4") %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="max-w-xl mx-auto bg-white shadow-md rounded rounded-t-none border-t-2 border-indigo-100 px-8 pt-6 pb-8 mt-10">
|
|
||||||
<h2 class="text-xl font-black">Goals</h2>
|
|
||||||
<div class="my-4 border-b border-gray-300"></div>
|
|
||||||
<div>
|
|
||||||
<%= if Enum.count(@goals) > 0 do %>
|
|
||||||
<%= for goal <- @goals do %>
|
|
||||||
<div class="border-b border-gray-300 py-3 flex justify-between">
|
|
||||||
<small class="font-bold"><%= goal_name(goal) %></small>
|
|
||||||
<%= button("❌", to: "/#{URI.encode_www_form(@site.domain)}/goals/#{goal.id}", method: :delete, class: "text-sm", data: [confirm: "Are you sure you want to remove goal #{goal_name(goal)}? This will just affect the UI, all of your analytics data will stay intact."]) %>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
<% else %>
|
|
||||||
<div>No goals configured for this site yet</div>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<%= link("+ Add goal", to: "/#{URI.encode_www_form(@site.domain)}/goals/new", class: "button mt-6") %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="max-w-xl mx-auto bg-white shadow-md rounded rounded-t-none border-t-2 border-indigo-100 px-8 pt-6 pb-8 mt-10" id="google-auth">
|
|
||||||
<h2 class="text-xl font-black">Google Integration</h2>
|
|
||||||
|
|
||||||
<div class="my-4 border-b border-gray-300"></div>
|
|
||||||
<div class="text-gray-700 my-4">
|
|
||||||
Integrating with your Google account allows Plausible to show more information about your websites' performance on their search engine.
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<%= if @site.google_auth do %>
|
|
||||||
<div class="py-2"></div>
|
|
||||||
<span class="text-gray-700">Linked Google account: <b><%= @site.google_auth.email %></b></span>
|
|
||||||
|
|
||||||
<%= link("Unlink Google account", to: "/#{URI.encode_www_form(@site.domain)}/settings/google", class: "inline-block mt-4 px-4 py-2 border border-gray-300 text-sm leading-5 font-medium rounded-md text-red-700 bg-white hover:text-red-500 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue active:text-red-800 active:bg-gray-50 transition ease-in-out duration-150", method: "delete") %>
|
|
||||||
|
|
||||||
<%= case @search_console_domains do %>
|
|
||||||
<% {:ok, domains} -> %>
|
|
||||||
<%= if @site.google_auth.property && !(@site.google_auth.property in domains) do %>
|
|
||||||
<p class="text-gray-700 mt-6 font-bold">
|
|
||||||
NB: Your Google account does not have access to your currently configured property, <%= @site.google_auth.property %>. Please select a verified property from the list below.
|
|
||||||
</p>
|
|
||||||
<% else %>
|
|
||||||
<p class="text-gray-700 mt-6">
|
|
||||||
Select the Google Search Console property you would like to pull keyword data from. If you don't see your domain, <%= link("set it up and verify", to: "https://docs.plausible.io/google-search-console-integration", class: "text-indigo-500") %> on Search Console first.
|
|
||||||
</p>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<%= form_for Plausible.Site.GoogleAuth.changeset(@site.google_auth), "/#{URI.encode_www_form(@site.domain)}/settings/google", [class: "max-w-xs"], fn f -> %>
|
|
||||||
<div class="my-6">
|
|
||||||
<div class="inline-block relative w-full">
|
|
||||||
<%= select f, :property, domains, prompt: "(Choose property)", class: "block appearance-none w-full bg-gray-100 text-gray-700 cursor-pointer hover:border-gray-500 p-2 pr-8 rounded leading-normal focus:outline-none" %>
|
|
||||||
<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-pink-500">
|
|
||||||
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z"/></svg>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<%= submit "Save", class: "button" %>
|
|
||||||
<% end %>
|
|
||||||
<% {:error, error} -> %>
|
|
||||||
<p class="text-gray-700 mt-6">The following error happened when fetching your Google Search Console domains.</p>
|
|
||||||
<p class="text-red-700 font-medium mt-3"><%= error %></p>
|
|
||||||
<% end %>
|
|
||||||
<% else %>
|
|
||||||
<%= button("Continue with Google", to: Plausible.Google.Api.authorize_url(@site.id), class: "button mt-4") %>
|
|
||||||
|
|
||||||
<div class="text-gray-700 mt-8">
|
|
||||||
NB: You also need to set up your site on <%= link("Google Search Console", to: "https://search.google.com/search-console/about") %> for the integration to work. <%= link("Read the docs", to: "https://docs.plausible.io/google-search-console-integration", class: "text-indigo-500") %>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="max-w-xl mx-auto bg-white shadow-md rounded rounded-t-none border-t-2 border-indigo-100 px-8 pt-6 pb-8 mt-10" id="email-reports">
|
|
||||||
<h2 class="text-xl font-black">Email reports</h2>
|
|
||||||
|
|
||||||
<div class="my-4 border-b border-gray-300"></div>
|
|
||||||
|
|
||||||
<div class="my-8 flex items-center">
|
|
||||||
<%= if @weekly_report do %>
|
|
||||||
<%= button(to: "/sites/#{URI.encode_www_form(@site.domain)}/weekly-report/disable", method: :post, class: "border rounded-full border-gray-300 flex items-center cursor-pointer w-8 bg-green-500 justify-end") do %>
|
|
||||||
<span class="rounded-full border w-4 h-4 border-gray-300 shadow-inner bg-white shadow"></span>
|
|
||||||
<% end %>
|
|
||||||
<% else %>
|
|
||||||
<%= button(to: "/sites/#{URI.encode_www_form(@site.domain)}/weekly-report/enable", method: :post, class: "border rounded-full border-gray-300 flex items-center cursor-pointer w-8 justify-start") do %>
|
|
||||||
<span class="rounded-full border w-4 h-4 border-gray-300 shadow-inner bg-white shadow"></span>
|
|
||||||
<% end %>
|
|
||||||
<% end %>
|
|
||||||
<span class="ml-2">Send a weekly email report every Monday</span>
|
|
||||||
</div>
|
|
||||||
<%= if @weekly_report do %>
|
|
||||||
<div class="text-sm text-gray-700 mt-6">
|
|
||||||
<h4 class="font-bold my-2">Weekly report recipients</h4>
|
|
||||||
<%= for recipient <- @weekly_report.recipients do %>
|
|
||||||
<div class="p-2 flex justify-between bg-gray-100 rounded my-2 max-w-md">
|
|
||||||
<span>
|
|
||||||
<svg class="feather mr-1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path><polyline points="22,6 12,13 2,6"></polyline></svg><%= recipient %>
|
|
||||||
</span>
|
|
||||||
<%= button("❌", to: "/sites/#{URI.encode_www_form(@site.domain)}/weekly-report/recipients/#{recipient}", method: :delete) %>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
<%= form_for @conn, "/sites/#{URI.encode_www_form(@site.domain)}/weekly-report/recipients", fn f -> %>
|
|
||||||
<div class="flex justify-between my-2 max-w-md">
|
|
||||||
<%= email_input f, :recipient, class: "transition bg-gray-100 appearance-none border border-transparent rounded w-full p-2 text-gray-700 leading-normal appearance-none focus:outline-none focus:border-gray-300", style: "flex-grow: 2", placeholder: "recipient@example.com" %>
|
|
||||||
<%= submit "Add recipient", class: "button rounded-l-none whitespace-no-wrap" %>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
<div class="my-8 border-b border-gray-300"></div>
|
|
||||||
<div class="my-8 flex items-center">
|
|
||||||
<%= if @monthly_report do %>
|
|
||||||
<%= button(to: "/sites/#{URI.encode_www_form(@site.domain)}/monthly-report/disable", method: :post, class: "border rounded-full border-gray-300 flex items-center cursor-pointer w-8 bg-green-500 justify-end") do %>
|
|
||||||
<span class="rounded-full border w-4 h-4 border-gray-300 shadow-inner bg-white shadow"></span>
|
|
||||||
<% end %>
|
|
||||||
<% else %>
|
|
||||||
<%= button(to: "/sites/#{URI.encode_www_form(@site.domain)}/monthly-report/enable", method: :post, class: "border rounded-full border-gray-300 flex items-center cursor-pointer w-8 justify-start") do %>
|
|
||||||
<span class="rounded-full border w-4 h-4 border-gray-300 shadow-inner bg-white shadow"></span>
|
|
||||||
<% end %>
|
|
||||||
<% end %>
|
|
||||||
<span class="ml-2">Send a monthly email report on 1st of the month</span>
|
|
||||||
</div>
|
|
||||||
<%= if @monthly_report do %>
|
|
||||||
<div class="text-sm text-gray-700 mt-6">
|
|
||||||
<h4 class="font-bold my-2">Monthly report recipients</h4>
|
|
||||||
<%= for recipient <- @monthly_report.recipients do %>
|
|
||||||
<div class="p-2 flex justify-between bg-gray-100 rounded my-2 max-w-md">
|
|
||||||
<span>
|
|
||||||
<svg class="feather mr-1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path><polyline points="22,6 12,13 2,6"></polyline></svg><%= recipient %>
|
|
||||||
</span>
|
|
||||||
<%= button("❌", to: "/sites/#{URI.encode_www_form(@site.domain)}/monthly-report/recipients/#{recipient}", method: :delete) %>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
<%= form_for @conn, "/sites/#{URI.encode_www_form(@site.domain)}/monthly-report/recipients", fn f -> %>
|
|
||||||
<div class="flex justify-between my-2 max-w-md">
|
|
||||||
<%= email_input f, :recipient, class: "transition bg-gray-100 appearance-none border border-transparent rounded w-full p-2 text-gray-700 leading-normal appearance-none focus:outline-none focus:border-gray-300", style: "flex-grow: 2", placeholder: "recipient@example.com" %>
|
|
||||||
<%= submit "Add recipient", class: "button rounded-l-none whitespace-no-wrap" %>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="bg-white max-w-xl mx-auto shadow-md rounded rounded-t-none border-t-2 border-indigo-100 px-8 pt-6 pb-8 mb-4 mt-16" id="custom-domain">
|
|
||||||
<h2 class="text-xl font-black">Custom domain</h2>
|
|
||||||
<div class="my-4">
|
|
||||||
You can serve the tracking script from your domain name as a first-party resource instead of loading the script from <code>plausible.io</code>.
|
|
||||||
</div>
|
|
||||||
<div class="mt-6">
|
|
||||||
<%= if @site.custom_domain do %>
|
|
||||||
Configured domain: <b><%= @site.custom_domain.domain %></b>
|
|
||||||
<%= link("Remove custom domain", to: "/sites/#{URI.encode_www_form(@site.domain)}/custom-domains/#{@site.custom_domain.id}", class: "inline-block mt-4 px-4 py-2 border border-gray-300 text-sm leading-5 font-medium rounded-md text-red-700 bg-white hover:text-red-500 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue active:text-red-800 active:bg-gray-50 transition ease-in-out duration-150", method: "delete") %>
|
|
||||||
<% else %>
|
|
||||||
<%= link("Add custom domain", to: "/sites/#{URI.encode_www_form(@site.domain)}/custom-domains/new", class: "button") %>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<%= form_for @conn, "/", [class: "bg-white max-w-xl mx-auto shadow-md rounded rounded-t-none border-t-2 border-indigo-100 px-8 pt-6 pb-8 mb-4 mt-16"], fn f -> %>
|
|
||||||
<h2 class="text-xl font-black">Javascript snippet</h2>
|
|
||||||
<div class="my-4">
|
|
||||||
<p>Include this snippet in the <code><head></code> of your website.</p>
|
|
||||||
<div class="relative">
|
|
||||||
<%= textarea f, :domain, id: "snippet_code", class: "transition overflow-hidden bg-gray-100 appearance-none border border-transparent rounded w-full p-2 pr-6 text-gray-700 leading-normal appearance-none focus:outline-none focus:bg-white focus:border-gray-300 text-xs mt-2 resize-none", value: snippet(@site), rows: 2 %>
|
|
||||||
<a onclick="var textarea = document.getElementById('snippet_code'); textarea.focus(); textarea.select(); document.execCommand('copy');" href="javascript:void(0)" class="no-underline text-indigo-500 text-sm hover:underline">
|
|
||||||
<svg class="absolute text-indigo-500" style="top: 24px; right: 12px;" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<div class="max-w-xl mx-auto bg-white shadow-md rounded rounded-t-none border-t-2 border-red-600 px-8 pt-6 pb-8 mt-16 mb-24">
|
|
||||||
<h2 class="text-xl font-black">Danger zone</h2>
|
|
||||||
|
|
||||||
<div class="my-4 border-b border-gray-300"></div>
|
|
||||||
|
|
||||||
<p class="text-gray-700">Resetting the stats removes all pageviews but keeps the site configuration</p>
|
|
||||||
<%= link("Reset #{@site.domain} stats", to: "/#{URI.encode_www_form(@site.domain)}/stats", method: :delete, class: "inline-block mt-4 px-4 py-2 border border-gray-300 text-sm leading-5 font-medium rounded-md text-red-700 bg-white hover:text-red-500 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue active:text-red-800 active:bg-gray-50 transition ease-in-out duration-150", data: [confirm: "Resetting the stats cannot be reversed. Are you sure?"]) %>
|
|
||||||
|
|
||||||
<div class="mt-6">
|
|
||||||
<p class="text-gray-700">Deleting the site removes all stats along with the site configuration</p>
|
|
||||||
<%= link "Delete #{@site.domain}", to: "/#{URI.encode_www_form(@site.domain)}", method: :delete, class: "inline-block mt-4 px-4 py-2 border border-transparent font-medium rounded-md text-red-700 bg-red-100 hover:bg-red-50 focus:outline-none focus:border-red-300 focus:shadow-outline-red active:bg-red-200 transition ease-in-out duration-150 sm:text-sm sm:leading-5", data: [confirm: "Deleting the site data cannot be reversed. Are you sure?"] %>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -0,0 +1,18 @@
|
|||||||
|
<div class="shadow bg-white sm:rounded-md sm:overflow-hidden py-6 px-4 sm:p-6">
|
||||||
|
<header class="relative">
|
||||||
|
<h2 class="text-lg leading-6 font-medium text-gray-900">Custom domain</h2>
|
||||||
|
<p class="mt-1 text-sm leading-5 text-gray-500">Serve the tracking script from your domain name as a first-party resource instead of loading the script from our domain.</p>
|
||||||
|
|
||||||
|
<%= link(to: "https://docs.plausible.io/custom-domain/", target: "_blank") do %>
|
||||||
|
<svg class="w-6 h-6 absolute top-0 right-0 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"></path></svg>
|
||||||
|
<% end %>
|
||||||
|
</header>
|
||||||
|
<div class="mt-6">
|
||||||
|
<%= if @site.custom_domain do %>
|
||||||
|
Configured domain: <b><%= @site.custom_domain.domain %></b>
|
||||||
|
<%= link("Remove custom domain", to: "/sites/#{URI.encode_www_form(@site.domain)}/custom-domains/#{@site.custom_domain.id}", class: "inline-block mt-4 px-4 py-2 border border-gray-300 text-sm leading-5 font-medium rounded-md text-red-700 bg-white hover:text-red-500 focus:outline-none focus:border-blue-300 focus:ring active:text-red-800 active:bg-gray-50 transition ease-in-out duration-150", method: "delete") %>
|
||||||
|
<% else %>
|
||||||
|
<%= link("Add custom domain", to: "/sites/#{URI.encode_www_form(@site.domain)}/custom-domains/new", class: "button") %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,32 @@
|
|||||||
|
<div class="sm:rounded-md sm:overflow-hidden shadow">
|
||||||
|
<div class="bg-white py-6 px-4 space-y-6 sm:p-6">
|
||||||
|
<div>
|
||||||
|
<h2 class="text-lg leading-6 font-medium text-gray-900">Danger zone</h2>
|
||||||
|
<p class="mt-1 text-sm leading-5 text-gray-500">Desctructive actions below can result in irrecoverable data loss. Be careful.</p>
|
||||||
|
</div>
|
||||||
|
<li class="py-4 flex items-center justify-between space-x-4">
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<p class="text-sm leading-5 font-medium text-gray-900">
|
||||||
|
Reset stats
|
||||||
|
</p>
|
||||||
|
<p class="text-sm leading-5 text-gray-500">
|
||||||
|
Removes all pageviews but keeps the site configuration
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<%= link("Reset #{@site.domain} stats", to: "/#{URI.encode_www_form(@site.domain)}/stats", method: :delete, class: "inline-block px-4 py-2 border border-gray-300 text-sm leading-5 font-medium rounded-md text-red-700 bg-white hover:text-red-500 focus:outline-none focus:border-blue-300 focus:ring active:text-red-800 active:bg-gray-50 transition ease-in-out duration-150", data: [confirm: "Resetting the stats cannot be reversed. Are you sure?"]) %>
|
||||||
|
</li>
|
||||||
|
<div class="border-b border-gray-200"></div>
|
||||||
|
|
||||||
|
<li class="py-4 flex items-center justify-between space-x-4">
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<p class="text-sm leading-5 font-medium text-gray-900">
|
||||||
|
Delete site
|
||||||
|
</p>
|
||||||
|
<p class="text-sm leading-5 text-gray-500">
|
||||||
|
Removes all stats along with the site configuration
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<%= link "Delete #{@site.domain}", to: "/#{URI.encode_www_form(@site.domain)}", method: :delete, class: "inline-block px-4 py-2 border border-transparent font-medium rounded-md text-red-700 bg-red-100 hover:bg-red-50 focus:outline-none focus:border-red-300 focus:ring active:bg-red-200 transition ease-in-out duration-150 sm:text-sm sm:leading-5", data: [confirm: "Deleting the site data cannot be reversed. Are you sure?"] %>
|
||||||
|
</li>
|
||||||
|
</div>
|
||||||
|
</div>
|
111
lib/plausible_web/templates/site/settings_email_reports.html.eex
Normal file
111
lib/plausible_web/templates/site/settings_email_reports.html.eex
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
<div class="shadow bg-white sm:rounded-md sm:overflow-hidden py-6 px-4 sm:p-6">
|
||||||
|
<header class="relative">
|
||||||
|
<h2 class="text-lg leading-6 font-medium text-gray-900">Email reports</h2>
|
||||||
|
<p class="mt-1 text-sm leading-5 text-gray-500">Send weekly/monthly analytics reports to as many addresses as you wish</p>
|
||||||
|
<%= link(to: "https://docs.plausible.io/email-reports/", target: "_blank") do %>
|
||||||
|
<svg class="w-6 h-6 absolute top-0 right-0 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"></path></svg>
|
||||||
|
<% end %>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="my-8 flex items-center">
|
||||||
|
<%= if @weekly_report do %>
|
||||||
|
<%= button(to: "/sites/#{URI.encode_www_form(@site.domain)}/weekly-report/disable", method: :post, class: "bg-indigo-600 relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring") do %>
|
||||||
|
<span class="translate-x-5 inline-block h-5 w-5 rounded-full bg-white shadow transform transition ease-in-out duration-200"></span>
|
||||||
|
<% end %>
|
||||||
|
<% else %>
|
||||||
|
<%= button(to: "/sites/#{URI.encode_www_form(@site.domain)}/weekly-report/enable", method: :post, class: "bg-gray-200 relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring") do %>
|
||||||
|
<span class="translate-x-0 inline-block h-5 w-5 rounded-full bg-white shadow transform transition ease-in-out duration-200"></span>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
<span class="ml-2">Send a weekly email report every Monday</span>
|
||||||
|
</div>
|
||||||
|
<%= if @weekly_report do %>
|
||||||
|
<div class="text-sm text-gray-700 mt-6">
|
||||||
|
<h4 class="font-bold my-2">Weekly report recipients</h4>
|
||||||
|
<%= for recipient <- @weekly_report.recipients do %>
|
||||||
|
<div class="p-2 pl-3 flex justify-between bg-gray-100 rounded my-2 max-w-md">
|
||||||
|
<span>
|
||||||
|
<svg class="h-5 w-5 text-gray-400 inline mr-3" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||||
|
<path d="M2.003 5.884L10 9.882l7.997-3.998A2 2 0 0016 4H4a2 2 0 00-1.997 1.884z" />
|
||||||
|
<path d="M18 8.118l-8 4-8-4V14a2 2 0 002 2h12a2 2 0 002-2V8.118z" />
|
||||||
|
</svg><%= recipient %>
|
||||||
|
</span>
|
||||||
|
<%= button(to: "/sites/#{URI.encode_www_form(@site.domain)}/weekly-report/recipients/#{recipient}", method: :delete) do %>
|
||||||
|
<svg class="w-4 h-4 text-red-600" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path></svg>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<%= form_for @conn, "/sites/#{URI.encode_www_form(@site.domain)}/weekly-report/recipients", fn f -> %>
|
||||||
|
<div class="max-w-md mt-4">
|
||||||
|
<div class="mt-1 flex rounded-md shadow-sm">
|
||||||
|
<div class="relative flex items-stretch flex-grow focus-within:z-10">
|
||||||
|
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||||
|
<svg class="h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||||
|
<path d="M2.003 5.884L10 9.882l7.997-3.998A2 2 0 0016 4H4a2 2 0 00-1.997 1.884z" />
|
||||||
|
<path d="M18 8.118l-8 4-8-4V14a2 2 0 002 2h12a2 2 0 002-2V8.118z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<%= email_input f, :recipient, class: "focus:ring-indigo-500 focus:border-indigo-500 block w-full rounded-none rounded-l-md pl-10 sm:text-sm border-gray-300", placeholder: "recipient@example.com" %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<%= submit class: "-ml-px relative button rounded-l-none" do %>
|
||||||
|
<svg class="w-5 h-5 mr-1" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M8 9a3 3 0 100-6 3 3 0 000 6zM8 11a6 6 0 016 6H2a6 6 0 016-6zM16 7a1 1 0 10-2 0v1h-1a1 1 0 100 2h1v1a1 1 0 102 0v-1h1a1 1 0 100-2h-1V7z"></path></svg>
|
||||||
|
<span>Add recipient</span>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<div class="my-8 border-b border-gray-300"></div>
|
||||||
|
<div class="my-8 flex items-center">
|
||||||
|
<%= if @monthly_report do %>
|
||||||
|
<%= button(to: "/sites/#{URI.encode_www_form(@site.domain)}/monthly-report/disable", method: :post, class: "bg-indigo-600 relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring") do %>
|
||||||
|
<span class="translate-x-5 inline-block h-5 w-5 rounded-full bg-white shadow transform transition ease-in-out duration-200"></span>
|
||||||
|
<% end %>
|
||||||
|
<% else %>
|
||||||
|
<%= button(to: "/sites/#{URI.encode_www_form(@site.domain)}/monthly-report/enable", method: :post, class: "bg-gray-200 relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring") do %>
|
||||||
|
<span class="translate-x-0 inline-block h-5 w-5 rounded-full bg-white shadow transform transition ease-in-out duration-200"></span>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
<span class="ml-2">Send a monthly email report on 1st of the month</span>
|
||||||
|
</div>
|
||||||
|
<%= if @monthly_report do %>
|
||||||
|
<div class="text-sm text-gray-700 mt-6">
|
||||||
|
<h4 class="font-bold my-2">Monthly report recipients</h4>
|
||||||
|
<%= for recipient <- @monthly_report.recipients do %>
|
||||||
|
<div class="p-2 pl-3 flex justify-between bg-gray-100 rounded my-2 max-w-md">
|
||||||
|
<span>
|
||||||
|
<svg class="h-5 w-5 text-gray-400 inline mr-3" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||||
|
<path d="M2.003 5.884L10 9.882l7.997-3.998A2 2 0 0016 4H4a2 2 0 00-1.997 1.884z" />
|
||||||
|
<path d="M18 8.118l-8 4-8-4V14a2 2 0 002 2h12a2 2 0 002-2V8.118z" />
|
||||||
|
</svg><%= recipient %>
|
||||||
|
</span>
|
||||||
|
<%= button(to: "/sites/#{URI.encode_www_form(@site.domain)}/monthly-report/recipients/#{recipient}", method: :delete) do %>
|
||||||
|
<svg class="w-4 h-4 text-red-600" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path></svg>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<%= form_for @conn, "/sites/#{URI.encode_www_form(@site.domain)}/monthly-report/recipients", fn f -> %>
|
||||||
|
<div class="max-w-md mt-4">
|
||||||
|
<div class="mt-1 flex rounded-md shadow-sm">
|
||||||
|
<div class="relative flex items-stretch flex-grow focus-within:z-10">
|
||||||
|
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||||
|
<svg class="h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||||
|
<path d="M2.003 5.884L10 9.882l7.997-3.998A2 2 0 0016 4H4a2 2 0 00-1.997 1.884z" />
|
||||||
|
<path d="M18 8.118l-8 4-8-4V14a2 2 0 002 2h12a2 2 0 002-2V8.118z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<%= email_input f, :recipient, class: "focus:ring-indigo-500 focus:border-indigo-500 block w-full rounded-none rounded-l-md pl-10 sm:text-sm border-gray-300", placeholder: "recipient@example.com" %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<%= submit class: "-ml-px relative button rounded-l-none" do %>
|
||||||
|
<svg class="w-5 h-5 mr-1" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M8 9a3 3 0 100-6 3 3 0 000 6zM8 11a6 6 0 016 6H2a6 6 0 016-6zM16 7a1 1 0 10-2 0v1h-1a1 1 0 100 2h1v1a1 1 0 102 0v-1h1a1 1 0 100-2h-1V7z"></path></svg>
|
||||||
|
<span>Add recipient</span>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
49
lib/plausible_web/templates/site/settings_general.html.eex
Normal file
49
lib/plausible_web/templates/site/settings_general.html.eex
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<%= form_for @changeset, "/#{URI.encode_www_form(@site.domain)}/settings", fn f -> %>
|
||||||
|
<div class="shadow sm:rounded-md sm:overflow-hidden">
|
||||||
|
<div class="bg-white py-6 px-4 space-y-6 sm:p-6">
|
||||||
|
<header class="relative">
|
||||||
|
<h2 class="text-lg leading-6 font-medium text-gray-900">General information</h2>
|
||||||
|
<p class="mt-1 text-sm leading-5 text-gray-500">Update your reporting timezone.</p>
|
||||||
|
<%= link(to: "https://docs.plausible.io/general/", target: "_blank") do %>
|
||||||
|
<svg class="w-6 h-6 absolute top-0 right-0 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"></path></svg>
|
||||||
|
<% end %>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-4 gap-6">
|
||||||
|
<div class="col-span-4 sm:col-span-2"> <%= label f, :domain, class: "block text-sm font-medium leading-5 text-gray-700" %>
|
||||||
|
<%= text_input f, :domain, class: "mt-1 block w-full shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:max-w-xs sm:text-sm border-gray-300 rounded-md", disabled: "disabled" %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-span-4 sm:col-span-2">
|
||||||
|
<%= label f, :timezone, "Reporting Timezone", class: "block text-sm font-medium leading-5 text-gray-700" %>
|
||||||
|
<%= select f, :timezone, Plausible.Timezones.options(), class: "mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md" %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="px-4 py-3 bg-gray-50 text-right sm:px-6">
|
||||||
|
<span class="inline-flex rounded-md shadow-sm">
|
||||||
|
<%= submit "Save", class: "bg-indigo-600 border border-transparent rounded-md py-2 px-4 inline-flex justify-center text-sm leading-5 font-medium text-white hover:bg-gray-700 focus:outline-none focus:border-gray-900 focus:ring active:bg-gray-900 transition duration-150 ease-in-out" %>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%= form_for @conn, "/", [class: "shadow bg-white sm:rounded-md sm:overflow-hidden py-6 px-4 sm:p-6"], fn f -> %>
|
||||||
|
<header class="relative">
|
||||||
|
<h2 class="text-lg leading-6 font-medium text-gray-900">Javascript snippet</h2>
|
||||||
|
<p class="mt-1 text-sm leading-5 text-gray-500">Include this snippet in the <code><head></code> of your website.</p>
|
||||||
|
|
||||||
|
<%= link(to: "https://docs.plausible.io/plausible-script", target: "_blank") do %>
|
||||||
|
<svg class="w-6 h-6 absolute top-0 right-0 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"></path></svg>
|
||||||
|
<% end %>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="my-4">
|
||||||
|
<div class="relative">
|
||||||
|
<%= textarea f, :domain, id: "snippet_code", class: "transition overflow-hidden bg-gray-100 appearance-none border border-transparent rounded w-full p-2 pr-6 text-gray-700 leading-normal appearance-none focus:outline-none focus:bg-white focus:border-gray-300 text-xs mt-2 resize-none", value: snippet(@site), rows: 2 %>
|
||||||
|
<a onclick="var textarea = document.getElementById('snippet_code'); textarea.focus(); textarea.select(); document.execCommand('copy');" href="javascript:void(0)" class="no-underline text-indigo-500 text-sm hover:underline">
|
||||||
|
<svg class="absolute text-indigo-500" style="top: 24px; right: 12px;" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
26
lib/plausible_web/templates/site/settings_goals.html.eex
Normal file
26
lib/plausible_web/templates/site/settings_goals.html.eex
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<div class="shadow bg-white sm:rounded-md sm:overflow-hidden py-6 px-4 sm:p-6">
|
||||||
|
<header class="relative">
|
||||||
|
<h2 class="text-lg leading-6 font-medium text-gray-900">Goals</h2>
|
||||||
|
<p class="mt-1 text-sm leading-5 text-gray-500">Define actions that you want your users to take like visiting a certain page, submitting a form, etc.</p>
|
||||||
|
<%= link(to: "https://docs.plausible.io/goal-conversions/", target: "_blank") do %>
|
||||||
|
<svg class="w-6 h-6 absolute top-0 right-0 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"></path></svg>
|
||||||
|
<% end %>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<%= if Enum.count(@goals) > 0 do %>
|
||||||
|
<div class="mt-4">
|
||||||
|
<%= for goal <- @goals do %>
|
||||||
|
<div class="border-b border-gray-300 py-3 flex justify-between">
|
||||||
|
<span class="text-sm font-medium text-gray-900"><%= goal_name(goal) %></span>
|
||||||
|
<%= button(to: "/#{URI.encode_www_form(@site.domain)}/goals/#{goal.id}", method: :delete, class: "text-sm text-red-600", data: [confirm: "Are you sure you want to remove goal #{goal_name(goal)}? This will just affect the UI, all of your analytics data will stay intact."]) do %>
|
||||||
|
<svg class="feather feather-sm" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path><line x1="10" y1="11" x2="10" y2="17"></line><line x1="14" y1="11" x2="14" y2="17"></line></svg>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<% else %>
|
||||||
|
<div class="mt-4">No goals configured for this site yet</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%= link("+ Add goal", to: "/#{URI.encode_www_form(@site.domain)}/goals/new", class: "button mt-6") %>
|
||||||
|
</div>
|
@ -0,0 +1,48 @@
|
|||||||
|
<div class="shadow bg-white sm:rounded-md sm:overflow-hidden py-6 px-4 sm:p-6">
|
||||||
|
<header class="relative">
|
||||||
|
<h2 class="text-lg leading-6 font-medium text-gray-900">Google Search Console integration</h2>
|
||||||
|
<p class="mt-1 text-sm leading-5 text-gray-500">You can integrate with Google Search Console to get all of your important search results stats such as keyword phrases people find your site with.</p>
|
||||||
|
<%= link(to: "https://docs.plausible.io/google-search-console-integration/", target: "_blank") do %>
|
||||||
|
<svg class="w-6 h-6 absolute top-0 right-0 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"></path></svg>
|
||||||
|
<% end %>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<%= if @site.google_auth do %>
|
||||||
|
<div class="py-2"></div>
|
||||||
|
<span class="text-gray-700">Linked Google account: <b><%= @site.google_auth.email %></b></span>
|
||||||
|
|
||||||
|
<%= link("Unlink Google account", to: "/#{URI.encode_www_form(@site.domain)}/settings/google", class: "inline-block mt-4 px-4 py-2 border border-gray-300 text-sm leading-5 font-medium rounded-md text-red-700 bg-white hover:text-red-500 focus:outline-none focus:border-blue-300 focus:ring active:text-red-800 active:bg-gray-50 transition ease-in-out duration-150", method: "delete") %>
|
||||||
|
|
||||||
|
<%= case @search_console_domains do %>
|
||||||
|
<% {:ok, domains} -> %>
|
||||||
|
<%= if @site.google_auth.property && !(@site.google_auth.property in domains) do %>
|
||||||
|
<p class="text-gray-700 mt-6 font-bold">
|
||||||
|
NB: Your Google account does not have access to your currently configured property, <%= @site.google_auth.property %>. Please select a verified property from the list below.
|
||||||
|
</p>
|
||||||
|
<% else %>
|
||||||
|
<p class="text-gray-700 mt-6">
|
||||||
|
Select the Google Search Console property you would like to pull keyword data from. If you don't see your domain, <%= link("set it up and verify", to: "https://docs.plausible.io/google-search-console-integration", class: "text-indigo-500") %> on Search Console first.
|
||||||
|
</p>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%= form_for Plausible.Site.GoogleAuth.changeset(@site.google_auth), "/#{URI.encode_www_form(@site.domain)}/settings/google", [class: "max-w-xs"], fn f -> %>
|
||||||
|
<div class="my-6">
|
||||||
|
<div class="inline-block relative w-full">
|
||||||
|
<%= select f, :property, domains, prompt: "(Choose property)", class: "mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md" %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<%= submit "Save", class: "button" %>
|
||||||
|
<% end %>
|
||||||
|
<% {:error, error} -> %>
|
||||||
|
<p class="text-gray-700 mt-6">The following error happened when fetching your Google Search Console domains.</p>
|
||||||
|
<p class="text-red-700 font-medium mt-3"><%= error %></p>
|
||||||
|
<% end %>
|
||||||
|
<% else %>
|
||||||
|
<%= button("Continue with Google", to: Plausible.Google.Api.authorize_url(@site.id), class: "button mt-8") %>
|
||||||
|
|
||||||
|
<div class="text-gray-700 mt-8">
|
||||||
|
NB: You also need to set up your site on <%= link("Google Search Console", to: "https://search.google.com/search-console/about") %> for the integration to work. <%= link("Read the docs", to: "https://docs.plausible.io/google-search-console-integration", class: "text-indigo-500") %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
@ -0,0 +1,52 @@
|
|||||||
|
<div class="shadow bg-white sm:rounded-md sm:overflow-hidden py-6 px-4 sm:p-6">
|
||||||
|
<header class="relative">
|
||||||
|
<h2 class="text-lg leading-6 font-medium text-gray-900">Public dashboard</h2>
|
||||||
|
<p class="mt-1 text-sm leading-5 text-gray-500">Share your stats publicly or keep them private</p>
|
||||||
|
<%= link(to: "https://docs.plausible.io/visibility", target: "_blank") do %>
|
||||||
|
<svg class="w-6 h-6 absolute top-0 right-0 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"></path></svg>
|
||||||
|
<% end %>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<%= if @site.public do %>
|
||||||
|
<div class="flex items-center space-x-3 mt-4">
|
||||||
|
<%= button(to: "/sites/#{URI.encode_www_form(@site.domain)}/make-private", method: "POST", class: "bg-indigo-600 relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring") do %>
|
||||||
|
<span class="translate-x-5 inline-block h-5 w-5 rounded-full bg-white shadow transform transition ease-in-out duration-200"></span>
|
||||||
|
<% end %>
|
||||||
|
<span class="text-sm leading-5 font-medium text-gray-900">Make stats publicly available on <a href="<%= plausible_url() <> "/" <> URI.encode_www_form(@site.domain)%>" class="text-indigo-500"><%= plausible_url() <> "/" <> URI.encode_www_form(@site.domain)%></a></span>
|
||||||
|
</div>
|
||||||
|
<% else %>
|
||||||
|
<div class="flex items-center space-x-3 mt-4">
|
||||||
|
<%= button(to: "/sites/#{URI.encode_www_form(@site.domain)}/make-public", method: "POST", class: "bg-gray-200 relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring") do %>
|
||||||
|
<span class="translate-x-0 inline-block h-5 w-5 rounded-full bg-white shadow transform transition ease-in-out duration-200"></span>
|
||||||
|
<% end %>
|
||||||
|
<span class="text-sm leading-5 font-medium text-gray-900">Make stats publicly available on <a href="<%= plausible_url() <> "/" <> URI.encode_www_form(@site.domain)%>" class="text-indigo-500"><%= plausible_url() <> "/" <> URI.encode_www_form(@site.domain)%></a></span>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="shadow bg-white sm:rounded-md sm:overflow-hidden py-6 px-4 sm:p-6">
|
||||||
|
<header class="relative">
|
||||||
|
<h2 class="text-lg leading-6 font-medium text-gray-900">Shared links</h2>
|
||||||
|
<p class="mt-1 text-sm leading-5 text-gray-500">You can share your stats privately by generating a shared link. The links are impossible to guess and you can add password protection for extra security.</p>
|
||||||
|
<%= link(to: "https://docs.plausible.io/shared-links", target: "_blank") do %>
|
||||||
|
<svg class="w-6 h-6 absolute top-0 right-0 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"></path></svg>
|
||||||
|
<% end %>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="mt-6">
|
||||||
|
<%= for link <- @shared_links do %>
|
||||||
|
<div class="flex relative w-full max-w-xl mt-2 text-sm">
|
||||||
|
<input type="text" id="<%= link.slug %>" readonly="readonly" value="<%= shared_link_dest(link) %>" class="transition bg-gray-100 appearance-none border border-transparent rounded rounded-r-none w-full p-2 text-gray-700 appearance-none focus:outline-none focus:border-gray-300" />
|
||||||
|
<button onclick="var input = document.getElementById('<%= link.slug %>'); input.focus(); input.select(); document.execCommand('copy');" href="javascript:void(0)" class="py-2 px-4 bg-gray-100 text-indigo-800 rounded-none border-r border-gray-300">
|
||||||
|
<svg class="feather-sm" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>
|
||||||
|
</button>
|
||||||
|
<%= button(to: "/sites/#{URI.encode_www_form(@site.domain)}/shared-links/#{link.slug}", method: :delete, class: "py-2 px-4 bg-gray-100 text-red-600 rounded-l-none", data: [confirm: "Are you sure you want to delete this shared link? The stats will not be accessible with this link anymore."]) do %>
|
||||||
|
<svg class="feather feather-sm" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path><line x1="10" y1="11" x2="10" y2="17"></line><line x1="14" y1="11" x2="14" y2="17"></line></svg>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%= link("+ New link", to: "/sites/#{URI.encode_www_form(@site.domain)}/shared-links/new", class: "button mt-4") %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -17,12 +17,12 @@
|
|||||||
</h2>
|
</h2>
|
||||||
<div class="mt-8 flex lg:flex-shrink-0 lg:mt-0">
|
<div class="mt-8 flex lg:flex-shrink-0 lg:mt-0">
|
||||||
<div class="inline-flex rounded-md shadow">
|
<div class="inline-flex rounded-md shadow">
|
||||||
<a href="/register" class="inline-flex items-center justify-center px-5 py-3 border border-transparent text-base leading-6 font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:shadow-outline transition duration-150 ease-in-out">
|
<a href="/register" class="inline-flex items-center justify-center px-5 py-3 border border-transparent text-base leading-6 font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-500 focus:outline-none focus:ring transition duration-150 ease-in-out">
|
||||||
Get started
|
Get started
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-3 inline-flex rounded-md shadow">
|
<div class="ml-3 inline-flex rounded-md shadow">
|
||||||
<a href="/" class="inline-flex items-center justify-center px-5 py-3 border border-transparent text-base leading-6 font-medium rounded-md text-indigo-600 bg-white hover:text-indigo-500 focus:outline-none focus:shadow-outline transition duration-150 ease-in-out">
|
<a href="/" class="inline-flex items-center justify-center px-5 py-3 border border-transparent text-base leading-6 font-medium rounded-md text-indigo-600 bg-white hover:text-indigo-500 focus:outline-none focus:ring transition duration-150 ease-in-out">
|
||||||
Learn more
|
Learn more
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -21,6 +21,19 @@ defmodule PlausibleWeb.LayoutView do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def settings_tabs() do
|
||||||
|
[
|
||||||
|
[key: "General", value: "general"],
|
||||||
|
[key: "Visibility", value: "visibility"],
|
||||||
|
[key: "Goals", value: "goals"],
|
||||||
|
[key: "Search Console", value: "search-console"],
|
||||||
|
[key: "Email reports", value: "email-reports"],
|
||||||
|
[key: "Custom domain", value: "custom-domain"],
|
||||||
|
[key: "Danger zone", value: "danger-zone"],
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
def trial_notificaton(user) do
|
def trial_notificaton(user) do
|
||||||
case Plausible.Billing.trial_days_left(user) do
|
case Plausible.Billing.trial_days_left(user) do
|
||||||
days when days > 1 ->
|
days when days > 1 ->
|
||||||
@ -36,4 +49,13 @@ defmodule PlausibleWeb.LayoutView do
|
|||||||
"Trial over, upgrade now"
|
"Trial over, upgrade now"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc "http://blog.plataformatec.com.br/2018/05/nested-layouts-with-phoenix/"
|
||||||
|
def render_layout(layout, assigns, do: content) do
|
||||||
|
render(layout, Map.put(assigns, :inner_layout, content))
|
||||||
|
end
|
||||||
|
|
||||||
|
def is_current_tab(conn, tab) do
|
||||||
|
List.last(conn.path_info) == tab
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user