- Add materialized views for list -> subscriber counts, dashboard chart,
and dashboard aggregate stats that slow down significantly on large
databases (with millions or tens of millions of subscribers). These
slow queries involve full table scan COUNTS().
- Add a toggle to enable caching slow results in Settings -> Performance.
- Add support for setting a cron string that crons and periodically
refreshes aggregated stats in materialized views.
Closes#1019.
- Upgrade eslint and fix a massive number (~2500!) of linting errors from new rules.
- Upgrade babel core frontend dev dependency.
- Upgrade UI lib and other frontend deps.
- Refactor the Vue admin app to use `vite` instead of `webpack`.
- This was an extremely tedious and painstaking, trial-and-error
alchemy job. My disdain for the Javascript "ecosystem" grows.
- Re-add custom admin appearance endpoints to the refactored Vue page.
- Remove obsolete vue-cli config.
- Re-auto-format all .vue files again to work with new linters.
- Adds support for arbitrary file uploads with an admin setting to select allowed file extensions.
- Adds support for attaching media (files) to campaigns.
- Add support for `complaint` to the SES bounce processor.
- Add support for `hard/soft` to Sendgrid bounce processor.
- Add new bounce actions `None` and `Unsubscribe`.
- Add per type (`soft/hard/complaint`) bounce rule configuration to
admin settings UI.
- Refactor Cypress bounce tests.
This is a long pending refactor. All the DB, query, CRUD, and related
logic scattered across HTTP handlers are now moved into a central
`core` package with clean, abstracted methods, decoupling HTTP
handlers from executing direct DB queries and other business logic.
eg: `core.CreateList()`, `core.GetLists()` etc.
- Remove obsolete subscriber methods.
- Move optin hook queries to core.
- Move campaign methods to `core`.
- Move all campaign methods to `core`.
- Move public page functions to `core`.
- Move all template functions to `core`.
- Move media and settings function to `core`.
- Move handler middleware functions to `core`.
- Move all bounce functions to `core`.
- Move all dashboard functions to `core`.
- Fix GetLists() not honouring type
- Fix unwrapped JSON responses.
- Clean up obsolete pre-core util function.
- Replace SQL array null check with cardinality check.
- Fix missing validations in `core` queries.
- Remove superfluous deps on internal `subimporter`.
- Add dashboard functions to `core`.
- Fix broken domain ban check.
- Fix broken subscriber check middleware.
- Remove redundant error handling.
- Remove obsolete functions.
- Remove obsolete structs.
- Remove obsolete queries and DB functions.
- Document the `core` package.
- Add new `headers[]` column to the campain table.
- Add new headers box to the campaign UI that takes a JSON array of
custom headers like the headers on the SMTP settings UI.
- Headers are added to e-mails and messenger postback webhooks.
- Add cypress tests.
Closes#514.
- Refactor codeflask HTML editor into a standalone html-editor
component.
- Replace the plaintext box in the template editor with html-editor.
- Replace codeflask in the campaign editor with the new html-editor.
- Refactor templates Cypress tests to test the new editor.
- Refactor campaigns Cypress tests to test the new editor and also
test switching between different editors and content formats.
E-mails in the domain blocklist are disallowed on the admin UI, public
subscription forms, API, and in the bulk importer.
- Add blocklist setting that takes a list of multi-line domains on the
Settings -> Privacy UI.
- Refactor e-mail validation in subimporter to add blocklist checking
centrally.
- Add Cypress testr testing domain blocklist behaviour on admin
and non-admin views.
Closes#336.
- Refactor subimporter New*() funcs to take opt structs.
- Refactor and simplify Vue code.
- Remove redundant i18n entries and use existing ones.
- Remove redundant subimporter constants and use existing ones.
- Consider 'overwrite' option for subscription status as well.
- Write Cypress integration tests for the new feature.
Sending th optional flag as `trunue` in the POST /api/subscrirs
body will skip sending opt-iconfirmation e-mails to subscribers
and mark list subscriptions in the request a`confirmed`.