* Clean up references to no longer active `google_analytics_imports` Oban queue
* Stub CSV importer
* Add SiteImport schema
* Rename `Plausible.Imported` module file to match module name
* Add `import_id` column to `Imported.*` CH schemas
* Implement Importer behavior and manage imports state using new entities
* Implement importer callbacks and maintain site.imported_data for UA
* Keep imports in sync when forgetting all imports
* Scope imported data queries to completed import IDs
* Mark newly imported data with respective import ID
* Clean up Importer implementation a bit
* Test querying legacy and new imported data
* Send Oban notifications on import worker failure too
* Fix checking for forgettable imports and remove redundant function
* Fix UA integration test
* Change site import source to atom enum and add source label
* Add typespecs and reduce repetition in `Plausible.Imported`
* Improve documentation and typespecs
* Add test for purging particular import
* Switch email notification templates depending on import source
* Document running import synchronously
* Fix UA importer args parsing and ensure it's covered by tests
* Clear `site.stats_start_date` on complete import to force recalculation
* Test Oban notifications (h/t @ruslandoga)
* Purge stats on import failure right away to reduce a chance of leaving debris behind
* Fix typos
Co-authored-by: hq1 <hq@mtod.org>
* Fix another typo
* Refactor fetching earliest import and earliest stats start date
* Use `Date.after?` instead of `Timex.after?`
* Cache import data in site virtual fields and limit queried imports to 5
* Ensure always current `stats_start_date` is used
* Work around broken typespec in Timex
* Make `SiteController.forget_imported` action idempotent
* Discard irrecoverably failed import tasks
* Use macros for site import statuses
There's also a fix ensuring only complete imports are considered
where relevant - couldn't isolate it as it was in a common hunk
* Use `import_id` as worker job uniqueness criterion
* Do not load imported stats data in plugins API context
---------
Co-authored-by: hq1 <hq@mtod.org>
* WIP: PropFilterRow
* Get multi-behavior working
* Render multiple prop filters in one
* Modal reads from query string correctly
* Backend support for multiple custom property filters
* Add backend tests for multiple custom property filters
* Disable already selected options in property keys
We can't allow choosing the same property multiple times without changing the request
params, which we decided against
* Allow choosing any property under Behaviors > Custom props even if custom prop filter applied
This was a limitation (I believe) introduced by using ARRAY JOINs to query custom properties
* CHANGELOG.md
* Solve credo warning about too deep nesting
* Update assets/js/dashboard/stats/modals/prop-filter-modal.js
Co-authored-by: RobertJoonas <56999674+RobertJoonas@users.noreply.github.com>
* Refactor internal function for clarity
* Add another step -> Add another
* Solve 500 error
* Separate boxes per property filter
* Retain other filters in props table
* removeFilter behavior for props
* matches_member support for custom props
* filter_suggestions for prop keys should account for prop filter
* find over filter
* refactor appliedFilters
* FILTER_TYPES => FILTER_OPERATIONS
* Make add another link not wrap the whole page
* Unique keys
---------
Co-authored-by: RobertJoonas <56999674+RobertJoonas@users.noreply.github.com>
* add tests for filtering by goal in timeseries and aggregate
* refactor filter parsing
* stop returning custom props in event:goal breakdown
* test breaking down wildcard pageview goals
* extract filter utils
* parse more goal filter options
* add passing tests for new filter types
* do not allow querying session metrics with a goal filter
* remove unused page_match property
* test that non-configured goals are not returned in breakdown
* enforce filtered goals configured
* update changelog
* Allow simple filtering by revenue goals
This does not mean that revenue metrics are supported. If a revenue goal
is filtered by, we treat it like a simple custom event goal in the API.
* use List.wrap
* Move imported tables schemas to separate modules outside Google ns
* Move buffer for imports to Imported ns
* fix schema newlines
* Extract UA import processing and persistence
* Decouple analytics worker implementation from UA
* Rename env variable for import buffer size
* Preserve old import queue until release
* Allow `matches` operator to work in BE for custom props
Note: No FE support yet, needs further testing
* feat: allow choosing `contains` for property filters in the UI
* no autocomplete on prop values if `contains` for consistency
* CHANGELOG.md
* Fix: Handle (none) property in property breakdowns when using matching
When matching we should always exclude (none)
* Fix a bug
This commit fixes a bug where the timeseries weekly interval query for a
month returned 0 visitors for the first week.
This happened because the start of the month defining the first week was
missing the UTC -> site.timezone conversion.
* Update test/plausible_web/controllers/api/stats_controller/main_graph_test.exs
Remove dot from test description
Co-authored-by: Karl-Aksel Puulmann <macobo@users.noreply.github.com>
---------
Co-authored-by: Karl-Aksel Puulmann <macobo@users.noreply.github.com>
* Fall back to UTC when timezone gap found
* bugfix 1
* bugfix 2
* Apply safe tz conversion to all cases where it's done on a ts other than now
---------
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
* remove unused code
* add e.name == "pageview" condition to pageview goals
This fixes the weird behavior where filtering by a pageview goal would
also return custom events and vice versa.
* update changelog
* restore special props access for growth plans
* format
* refactor if condition
Co-authored-by: hq1 <hq@mtod.org>
* format
---------
Co-authored-by: hq1 <hq@mtod.org>
* Move limit enforcement to accepting site ownerhsip transfer
* enforce pageview limit on ownership transfer accept
* Refactor plan limit check logic
* Extract `ensure_can_take_ownership` to `Invitations` context and refactor
* Improve styling of exceeded limits notice in invitation dialog and disable button
* styling improvements to notice
* make transfer_ownership return transfer to self error
* do not allow transferring to user without active subscription WIP
* Add missing typespec and improve existing ones
* Fix formatting
* Explicitly label direct match on function argument for clarity
* Slightly refactor `CreateInvitation.bulk_transfer_ownership_direct`
* Exclude quota enforcement tests from small build test suite
* Remove unused return type from `invite_error()` union type
* Do not block plan upgrade when there's pending ownership transfer
* Don't block and only warn about missing features on transfer
* Remove `x-init` attribute used for debugging
* Add tests for `Quota.monthly_pageview_usage/2`
* Test and improve site admin ownership transfer actions
* Extend tests for `AcceptInvitation.transfer_ownership`
* Test transfer ownership controller level accept action error cases
* Test choosing plan by user without sites but with a pending ownership transfer
* Test invitation x-data in sites LV
* Remove sitelocker trigger in invitation acceptance code and simplify logic
* Add Quota test for `user.allow_next_upgrade_override` being set
* ignore pageview limit only when subscribing to plan
* Use sandbox Paddle instance for staging
* Use sandbox paddle key for staging and dev
---------
Co-authored-by: Robert Joonas <robertjoonas16@gmail.com>
* Remove business tier feature flag
This commit removes all code branches related to the business tier
feature flag, as we're not flipping this flag off anymore. It also
removes unused routes, e.g. /billing/change-plan and /billing/upgrade
* remove unused billing templates
* refactor with clause to case instead
* assert on the url in email tests
---------
Co-authored-by: Robert Joonas <robertjoonas16@gmail.com>
* remove unused functionality
We can now safely delete all the logic around users who are on trial and
signed up *before* the business tiers release, since that's no longer
possible
* add monthly_pageview_limit fn clause that takes a user
* make Quota.site_limit return enterprise site limit
...not `:unlimited`, as we still need to display it
in the account settings.
* make `team_member_limit/1` return :unlimited on small_build
* improve team_member_usage/1 function doc
* stop displaying unlimited symbol in usage section
These unlimited limits include:
* `monthly_pageview_limit` for trials
* `team_member_limit` for old enterprise plans
* `site limit` for old accounts (before 2021-05-05)
* format
* small refactor case clause + move mod vars
* review suggestions
* Add 2FA actions to `AuthController`
* Hook up new `AuthController` actions to router
* Add `qr_code` to project dependencies
* Implement generic `qr_code` component rendering SVG QR code from text
* Implement enabled and disabled 2FA setting state in user settings view
* Implement view for initiating 2FA setup
* Implement view for verifying 2FA setup
* Implement view for rendering generated 2FA recovery codes
* Implement view for verifying 2FA code
* Implement view for verifying 2FA recovery code
* Improve `input_with_clipboard` component
* Improve view for initiating 2FA setup
* Improve verify 2FA setup view
* Implement `verify_2fa_input` component
* Improve view for verifying 2FA setup
* Improve view rendering generated 2FA recovery codes
* Use `verify_2fa_input` component in verify 2FA view
* Do not render PA contact on self-hosted instances
* Improve flash message phrasing on generated recovery codes
* Add byline with a warning to disable 2FA modal
* Extract modal to component and move 2FA components to dedicated module
* First pass on loading state for "generate new codes"
* Adjust modal button logic
* Fix button in verify_2fa_input component
* Use button component in activate view
* Implement wait states for recovery code related actions properly
* Apply rate limiting to 2FA verification
* Log failed 2FA code input attempts
* Add ability to trust device and skip 2FA for 30 days
* Improve styling in dark mode
* Fix waiting state under Chrome and Safari
* Delete trust cookie when disabling 2FA
* Put 2FA behind a feature flag
* Extract 2FA cookie deletion
* ff fixup
* Improve session management during 2FA login
* Extract part of 2FA controller logic to a separate module and clean up a bit
* Clear 2FA user session when rate limit hit
* Add id to form in verify 2FA setup view
* Add controller tests for 2FA actions and login action
* Update CHANGELOG.md
* Use `full_build?()` instead of `@is_selfhost` removed after rebase
* Update `Auth.TOTP` moduledoc
* Add TOTP token management and make `TOTP.enable` more test-friendly
* Use TOTP token for device trust feature
* Use zero-deps `eqrcode` instead of deps-heavy `qr_code`
* Improve flash messages copy
Co-authored-by: hq1 <hq@mtod.org>
* Make one more copy improvement
Co-authored-by: hq1 <hq@mtod.org>
* Fix copy in remaining spots
* Change redirect after login to accept URLs from #3560 (h/t @aerosol)
* Add tests checking handling login_dest on login and 2FA verification
* Fix regression in email activation form submit button behavior
* Rename `PlausibleWeb.TwoFactor` -> `PlausibleWeb.TwoFactor.Session`
* Move `qr_code` component under `Components.TwoFactor`
* Set domain and secure options for new cookies
---------
Co-authored-by: hq1 <hq@mtod.org>
* Avoid redirect in site settings
* Fix unicode in SiteController existing tests
* Fix various tests
* Add CHANGELOG
* Make sure test site is example.com
* Use Route helpers in site_controller
* Fix UTF redirect in change domain submit action
* Fix UTF site domain in reset stats action
* refactor asking for the monthly pageview usage
* add tests for usage and limits section in account settings
* display pageview usage per billing cycle for active subscribers
* disable cycle tabs if no usage
* make current billing cycle whole
...instead of capping it at today's date
* run queries for different cycles concurrently
* fix linebreak bug
* add calculate usage action into CRM
* change some names of assigns
* block subscribing to a plan by pageview usage
Depending on whether the customer has already subscribed or not, checking
their pageview usage is different:
* If they're not subscribed yet, we allow them to subscribe to a plan If
it their last 30 days usage does not exceed the plan pageview limit by
more than 15% (30% for when subscribing to a 10k plan)
* For existing subscribers, we'll use the exact same mechanism that we're
using for locking sites - the last two billing cycles usage. If both
cycles exceed the plan limit by more than 10% - we don't allow them to
subscribe to the plan
* apply credo suggestion
* prevent highlight bar overflow
* move disabled classes to button element
* optimize for darkmode
* unify link and text styling on the same horizontal line
'Upgrade' & 'Update billing details' links + billing interval text were
positioned on the same line. The font size was similar, but not the same
* improve exceeded_limits function readability
* Refactor some tests and remove code duplication
* override allow upgrade when limits exceeded
In cases where limits are exceeded, we can set the boolean flag
`allow_next_upgrade_override` to `true` in the CRM. This will allow
the user to upgrade to any plan they want. After they've upgraded or
changed their plan - the flag will automatically reset to `false`.
* only apply upgrade override for exceeded pageview limit
* fix tests on the CI
* make current_cycle usage always displayed by default
* make pageview allowance margin more clear
* add comment
* Disable super-admin checks on small build
* Mute a test writing to stdout
* Move sampling outside of small build
* Convert waiting_first_pageview to heex and stop relying on env vars
* Set site limit unlimited on small build
* Stop relying on app env to get trial expiry
* Remove custom domains - including migration
* Remove is_selfhosted from layout view
* Quota fixup
* Stop relying on app env for self hosted registration
* Stop relying on app env for pass reset success
* Apply on_trial? check only on full build
* Update templates relying on app env
* Adjusts auth controller tests for small build
* Trial fixup
* Fixup
* Stop relying on app env
* Rest of the fsckn owl
* Update typespecs
* Fix dialyzer warning
* Remove unused module
* Credo + format
* GeoIP is not, for full build
* Use `small_build?()` where applicable
* Implement bypassing FirstLaunchPlug without insertions
* Get Marko's patch de58a18a85
* Test is-dbip=false presence
* Fix typespec
* Remove future hardcodes
* Handle `nil` from `Plausible.Geo.database_type()`
* Remove XXX marker
* Use one typespec for two clauses
* Introduce `MIX_ENV=small_dev`
* Revert "Use one typespec for two clauses"
This reverts commit 8d8cd21764.
* Update applications
* Clone community config
* Move modules to experimental dir
* Update runtime config
* Apply first set of compile-time conditionals
* Move funnel schemas to experimental
* Make funnel schema-less build compile
* Use experimental/lib for elixir code
* Move JS funnels to experimental
* Clean up conditional rendering
* Tidy up the pipeline
* Make two builds pass tests without warnings
* Reuse existing dotenvs
* Do a bunch of renames
* Clean up naming
* Run secondary CI
* Update router
* Remove RewriteFunnelDupes migration
Tests were disabled already and it was a one-off shot
* Fixup quota mixins
* Add moduledoc
* Change MIX_ENV for seconary test run
* Skip crm on small
* !fixup
* Exclude flags pipeline
* Update lib/plausible_web/controllers/stats_controller.ex
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
---------
Co-authored-by: Adrian Gruntkowski <adrian.gruntkowski@gmail.com>
* refactor asserting plan generation in plans_test.exs
* stop grandfathering old expired trials
For users who registered before the business tiers release, we want to
offer a chance to subscribe to a grandfathered plan. However, if they
let their trial expire and don't subscribe in the next 10 days, they'll
lose that opportunity.
* stop grandfathering expired subscriptions
* remove default title and icon from Generic.notice
* fix bug with dismissable notice
classList is null when dismissable_id is not given
* alias Plausible.Auth.User
* Refactor Generic.notice component
Make it easy to apply different colors
* move subscription_cancelled_notice across the app
And remove from user settings > subscription box. Also, include a note
about losing grandfathered status when letting the subscription expire.
* allow full width in Generic.notice
* use Generic.notice for subscription_past_due_notice
* use Generic.notice for subscription_paused_notice
* prevent two notices clashing into each other with gap-y-2
* define attrs for phx components
* optimize for light mode
* make subscription cancelled notice dismissable
but if it's dismiss, show it in the place where it was before in the
account settings > subscription box
* make function private
* replace function doc with regular comment to avoid compile warning
* use array for classnames
Co-authored-by: Vinicius Brasil <vini@hey.com>
* fix typos in function doc
---------
Co-authored-by: Vinicius Brasil <vini@hey.com>
* use windows in 'time on page' query
* add imported time on page back
* join imported_pages instead of extra query
* don't forget aggregated time on page!
* eh?
* no need for separate window clause
* use dynamic_filter_condition in aggregate_time_on_page
* it's avg, not total
* fix dynamic_filter_condition call
* tests pass
* fewer changes
* fewer changes + feature flag
* base quickfix
* fewer changes
* fewer changes?
* fewer changes!
* replace coalesce with if(empty(),etc)
* make window_aggregate_time_on_page return same result as neighbor_
* breakdown as well
* add failing test
* more info
* more info
* format example
* add failing aggregate.ex test
* fix breakdown.ex windowing time_on_page calculation
* fix aggregate.ex windowing time_on_page calculation
* Revert "Remove site pins for now"
This reverts commit 5eccf4eaf6.
* Implement basic site pin schema level logic within user specific preferences
* Add vertical ellipsis menu markup
* Implement basic changesets for user preferences
* Implement pin toggling
* Try to fix pin sorting
* Implement pin toggling in LV
* Adjust moduledocs for new schema(s)
* Remove unnecessary `distinct` from query
* Use `button` for pin/unpin action
* Generalize preference setting
* Rename schema and fields for clarity
* Rename `list_type` -> `entry_type`
* Safeguard setting options
* Test `set_option/4` and `toggle_pin/2`
* Add test for listing pinned sites via `Sites.list`
* Disallow pinning sites outside page explicitly
* Test pinning in LV
* Test conditional rendering of site settings in /sites
* Remove unnecessary TODO comment
* Safeguard `Sites.set_option/4` against invalid user/site combo
* Handle pinned sites in dashboard site picker
* Clear flashes upon (un)pinning sites
* Update CHANGELOG
* Prevent blinking of hamburger menu items on first paint
* Highlight hamburger handle on hover in /sites
* Start showing hotkeys in site picker again
* Sort pinned sites in the order they were pinned
* Update sites list order immediately after pin/unpin toggle
* Refactor and split `Sites.list/3`, extracting `Sites.list_with_invitations/3`
* Cap number of pinned sites at 9 per user
* First pass on visual indication of site cards (dis)appearing
* Apply ellipsis gradient+shadow on card hover
* Fix responsive padding of site cards
* Sort by invitations first, pinned sites second and then the rest
* Revert "Apply ellipsis gradient+shadow on card hover"
This reverts commit 0608796612639030ccbb12df639709f78edc1434.
* Apply more subtle hover effect on the ellipsis menu
* Make error and success flash LV boxes use separate component containers
* Promote `pinned_at` in table migration to a column
* Switch logic to using `pinned_at` as a standard schema field
* Refactor `Sites.list*` getting rid of subquery (h/t @ukutaht)
* Remove migration which is already merged upstream
---------
Co-authored-by: Adam Rutkowski <hq@mtod.org>
* fix underlined blank space in upgrade link
* Add :if clause to site limit notice
* Change test description
* Move growth? and trial? conditionals to CTA function
* Improve wording in billing notices
---------
Co-authored-by: Vinicius Brasil <vini@hey.com>
* Fix private preview notice typo
* fix link to choose-plan instead of upgrade
* do not display premium feature notice if legacy feature access
* register trial message
* change enterprise contact us copy
* fix test
---------
Co-authored-by: Robert Joonas <robertjoonas16@gmail.com>
* price formatting
* fix space underlined
* add a redirect from :upgrade to :choose_plan
* Add premium feature notice to revenue goals
* add the number of API request to plan benefits
* be more explicit about Stats API requests
* start linking to the new upgrade page if FF enabled
* add redirect to :upgrade_to_enterprise_plan from :choose_plan
This commit intends to keep the existing behaviour of redirecting users
directly to the enterprise upgrade page when they click on an upgrade
link in an email and have an enterprise plan configured.
Hence, we can also simplify the /settings template and only link to
'/billing/choose-plan', even for enterprise plans.
* deprecate /billing/change-plan route based on FF
* Move new site template to HEEX
* Move new team member invitation template to HEEX
* Standardize exceeded limits error message
* Fix failing tests
* Limit Stats API access to unlimited trials
---------
Co-authored-by: Vinicius Brasil <vini@hey.com>