fixes https://github.com/TryGhost/Team/issues/3541
The email preheader, which is only present in the html version of an
email, is also included in the plaintext version of all emails. This
results in all text being duplicated twice in plaintext emails.
fixes https://github.com/TryGhost/Ghost/issues/16131
Members only content was incorrectly being shown in a plaintext email
due to the email `preheader` using the post model `plaintext` field
directly (which contained the members-only content). This changes this
behaviour so that the post html content is utilised for the `preheader`
but has all members-only content (post-preview content + segmented
content) removed
We setup the relations and NQL expansions/replacements here rather than in the
repository, we want to keep all the bookshelf code together in one place.
We couldn't decide on the best way to encode this in the database.
e.g. deletable: true? or type: internal? but type conflicts with the
storage of manual/automatic.
For now we can use this, and add something in future if we're finding problems
When we end up wiring this to the database, this generator will also ensure
uniqueness by appending/incrementing a number on the end of the slug. Long term
it would be good to offload this to a shared slug service, this could also
ensure that slugs are unique globally or between multiple tables, if desired
We require that slugs are unique as slugs can/are used for routing purposes and
act as an identifier for a resource. As this is a core business rule, we want
to encode it in the entity so that it can be unit tested, and be enforced
regardless of underlying persistence layer
This follows our existing patterns and protects us from th eslint max line rule
when wiring up dependencies. The rule is designed to keep logic out of glue
code, and this file won't have logic, just lots of deps.
refs https://github.com/TryGhost/Team/issues/3169
- The "current" part of the payload should always have the "id" included to make the data structure easier to use for the event consumer
refs https://github.com/TryGhost/Team/issues/3169
- With the new architecture all possible dependencies should be injected rather than required directly - this applies to the DomainEvents module as well.
refs https://github.com/TryGhost/Team/issues/3169
- When a not yet mapped event is produced by Ghost model the posts belonging to a collection are recalculated in a brute-force way. This causes a lot of strain on the database and times out some of the tests. Right now we only care about a handful of events, so limited the ones we listen to and will be uncommenting the rest when we have an optimal mapping/handling for them.
refs https://github.com/TryGhost/Team/issues/3169
- To be able to apply NQL filtering on Collection Posts the dates should be serialized to be ISO Date Strings instead of raw Dates. Otherwise, NQL filtering fails to compare Date with a Date String.
refs https://github.com/TryGhost/Team/issues/3169
- This piece of logic handles the 'post.added' model event mapping to Collection's PostAddedEvent domain event and logic related to updating collections when the new post is added.
refs https://github.com/TryGhost/Team/issues/3169
- The collection entity properties used to be modified, which is not a good practice for logic encapsulation. Extracted editing logic to it's own method which can also contain validation logic when wrong data is passed when editing a collection.
refs https://github.com/TryGhost/Team/issues/3169
- When handling a single generic event the code becomes riddled with if statements to detect correct "data" that is being passed with the event. Switching to have a domain event per model event helps solving this problem and makes code more readable.
refs https://github.com/TryGhost/Team/issues/3169
- To make the coupling to Ghost's model events as loose as possible added a bridge that maps model events to domain events. These domain events it what the collections module can subscribe to to make necessary updates.
refs https://github.com/TryGhost/Team/issues/3169
- Ghost model events should not be crossing emitted to outside libraries. The wrapper code is a "glue code" that can still listen to model events but transforms them to specific format that is useful for the collections module
- This hooks up the Ghost model events and transforms them into a "CollectionEvent" format.
refs https://github.com/TryGhost/Team/issues/3428
- I'm taking an approach of adding specialized support for each event one-by-one.
- The post resource deletion event is the most straight forward and works same for both types of collections.
refs https://github.com/TryGhost/Toolbox/issues/602
- the new regex allows for the filename to contain seconds, which would have
helped prevent a bug we had with migrations being in the wrong order
- mentioned filename ordering in the migration review comment to bring
that to the forefront of the mind
refs https://github.com/TryGhost/Ghost/issues/15725
This pull request adds a new configuration option for the Mailgun email
provider that allows the user to set the maximum number of recipients
per email batch via a new config option `bulkEmail.batchSize`
closes https://github.com/TryGhost/Team/issues/2463
- it merges the similar history events by adding additional properties
to the events data
- `skip` was added to the current event when the next event is similar to
it, so that the event isn't output on the frontend
- `count` was added to the last item of the similar events and it's used
for outputting the number of repeated similar events
fixes https://github.com/TryGhost/Ghost/issues/17125
- both collections migrations have the same timestamp so they're ordered
based upon their slug name, and the one that creates
`collections_posts` is ordered before the one that created
`collections`
- as a result, the migration fails because the table does not exist
- this commit pushes the `collections_posts` migration after the other
one by bumping the timestamp
no issue
Keep an eye on Ghost's changelog (https://ghost.org/changelog/) for the
full feature announcement.
<!-- Leave the line below if you'd like GitHub Copilot to generate a
summary from your commit -->
<!--
copilot:summary
-->
### <samp>🤖 Generated by Copilot at ee03e4d</samp>
This pull request removes the `signupCard` feature flag and enables the
signup card for all users in the Lexical editor. This is part of the
Lexical editor beta release, which is a new editor for Ghost that
provides a better writing experience and more features for content
creators.
closes https://github.com/TryGhost/Team/issues/3521
When duplicating a newsletter (email only post) some of the fields
relating to the newsletter (i.e `newsletter_id`) were being erroneously
copied over. Upon publishing this made the post appear as if it was an
email only post that had been sent to subscribers when it actually had
not
fixes https://github.com/TryGhost/Ghost/issues/16120
- if you set `sodoSearch.url` to `false` in config, it'll currently
crash because we're not correctly handling the types correctly
- the first part of the fix is ensuring the value is a string so we can
call `.includes` on it
- second, the `false` value is passed into the output as a string, so we
should detect if we passed a false value and early return with an
empty string if so
- credits to https://github.com/ltoinel for the fix inspiration
- Updated test request records to be distinct per API call
- Updated design tests to check preview data
- Added tests for navigation settings
refs https://github.com/TryGhost/Team/issues/3349
- in the migration tests we need to boot Ghost and then kill it
afterwards
- because there was no easy way to do this, the workflow waits for 20s
and then kills the last process ID
- aside from being a terrible idea, it means we're also just arbitrarily
waiting for 20s, which burns time when it takes shorter to boot Ghost
- this commit implements an environment variable that will kill the
server once it has run the whole boot process, and then fixes the
workflow to use that
refs https://github.com/TryGhost/Team/issues/3504
- Sentry was never setup and we don't use it
- Styles have been moved to inline JS styles (no separate css file generated)
- App version was never used
- Improved current script tag detection
fixes https://github.com/TryGhost/Ghost/issues/17076
When a post is saved `_revisionSaveTask` gets queued to execute 10
minutes from the save. When a post is published via the publish modal
`_revisionSaveTask` does not get dequeued. When `_revisionSaveTask` gets
executed at the 10 minute mark it is assumed that it is ok to save a
revision, which will cause the post to be reverted back to a draft. This
change enforces another check during the task exection to ensure that it
is in fact still ok to save a revision (in case anything has changed in
the 10 minutes since the task queued, i.e the post being published)
fixes https://github.com/TryGhost/Team/issues/3505
I've investigated this, but luckily this is expected behaviour, and was just an error previously in the test:
- The `feedback_more_like_this` and `feedback_less_like_this` columns are only hidden if there is no newsletter with feedback enabled, or if member features are disabled.
- Having a post which is a draft, should not change the visible columns, only global settings should change the comments (so the format is consistent).
- Instead of that, the columns should be null, which means it will be visible but empty.
fixes https://github.com/TryGhost/Ghost/issues/17076
When a post is saved `_revisionSaveTask` gets queued to execute 10
minutes from the save. When a post is published via the publish modal
`_revisionSaveTask` does not get dequeued. When `_revisionSaveTask` gets
executed at the 10 minute mark it is assumed that it is ok to save a
revision, which will cause the post to be reverted back to a draft. This
change enforces another check during the task exection to ensure that it
is in fact still ok to save a revision (in case anything has changed in
the 10 minutes since the task queued, i.e the post being published)
closes https://github.com/TryGhost/Team/issues/3493
- Fixed pages not saving on force revision. As a side effect, it broke
admin navigation as it doesn't manage to create a new revision upon going back to the pages list.
- This was simply caused by a missing option in the API endpoint config.
---
<!-- Leave the line below if you'd like GitHub Copilot to generate a
summary from your commit -->
<!--
copilot:summary
-->
### <samp>🤖 Generated by Copilot at b646916</samp>
This change enables the `pages` endpoint to handle page revisions by
adding the `save_revision` permission. This is part of a pull request
that adds page versioning and restoring functionality to Ghost.
refs: https://github.com/TryGhost/Toolbox/issues/595
We're rolling out new rules around the node assert library, the first of which is enforcing the use of assert/strict. This means we don't need to use the strict version of methods, as the standard version will work that way by default.
This caught some gotchas in our existing usage of assert where the lack of strict mode had unexpected results:
- Url matching needs to be done on `url.href` see aa58b354a4
- Null and undefined are not the same thing, there were a few cases of this being confused
- Particularly questionable changes in [PostExporter tests](c1a468744b) tracked [here](https://github.com/TryGhost/Team/issues/3505).
- A typo see eaac9c293a
Moving forward, using assert strict should help us to catch unexpected behaviour, particularly around nulls and undefineds during implementation.
refs TryGhost/Ghost#3494
- By default, the post scheduler runs as user_id = 1, which is the
original owner of the site
- If ownership has been transferred to a different user, it's possible
that there is no user with id = 1
- In this case, the scheduler would fail to publish a post, because
updating the post using user_id = 1 failed a foreign key constraint in
the post_revisions table
- This commit fixes the issue by checking if the contextUser exists, and
if not, replacing it with the current owner of the site
no issue
Updates the labels of the post history components to reflect the type of
content (post or page).
It modifies the `restore-revision`, `gh-post-settings-menu`, and
`modal-post-history` components.
no issue
- even when the editor beta is turned off, any post created in the beta will still open in the beta editor
- the "beta feedback" text in the bottom right was disabled when the beta flag was disabled which meant it was difficult to tell when you were using the beta editor vs the original editor
no issue
- even when the editor beta is turned off, any post created in the beta will still open in the beta editor
- the "beta feedback" text in the bottom right was disabled when the beta flag was disabled which meant it was difficult to tell when you were using the beta editor vs the original editor
closes https://github.com/TryGhost/Team/issues/3499
- bumps `@tryghost/kg-default-nodes` and `@tryghost/kg-lexical-html-renderer` to fix missing `kg-image` class on the `<img>` element of rendered image cards
refs https://github.com/TryGhost/Team/issues/3169
- When navigating through collections slugs did not display correctly returning "undefined" in the navigation. It was easier to fix the bug than working around it.
refs https://github.com/TryGhost/Team/issues/3432
The admin assets url are modified by ember build process by adding cache busting, so the original urls can't be used directly in adminX. This change passes the image assets from ember admin, causing the right image urls to be passed to adminX and for loading images.
refs https://github.com/TryGhost/Toolbox/issues/592
- it turns out that `TRUNCATE` in CI takes ~300ms for all tables, but
`DELETE FROM` takes ~30ms
- whilst truncating is generally known to be faster, I believe it's only
faster on large tables
- this saves 90% of the time it takes to reset the DB in MySQL
closes https://github.com/TryGhost/Team/issues/3423
- For convenience we need a way to fetch posts that belong to a certain collection. This change adds support for `collection` query parameter: `/?collection=` which can be either an id or slug of the collections we are trying to fetch.
- When posts are fetched by collection we ignore any filters passed along in query parameters as collection is a "filter" by it's very nature.
refs 997cd3687e
- the `eslint-config-react-app` dependency already covers all necessary rules from `eslint-plugin-react`
and using it separately causes conflicts across projects in eslint config
- thanks for the commit message @rishabhgrg :)
The `eslint-config-react-app` already covers all necessary rules from `eslint-plugin-react` and using it separately causes conflicts across projects in eslint config
refs https://github.com/TryGhost/Team/issues/3423
- This is a convenience method that should allow fetching collections by their slug. It is a great developer experience for in case when fetching built-in collections like "featured" and "index", so can avoid an extra call to find the collection and it's ide one wants to use.
no issue
This was a bit of an oversight from our feature built at the retreat. We
didn't take revisions into account for pages at all, but luckily it made
revisions without issues regardless.
It just wasn't accessible and users weren't able to restore via ADMIN
because the API didn't serve them at all.
This wires up the revisions relation to be served by the API so we can
retrieve it in Admin.
We've got some fairly simple diffing logic here to update the collections which
a post is in, the bulk of the changes here are to support the return of a DTO
rather than Bookshelf Model. This also helps improve the architecture because
we are step closer to removing infrastructure concerns (HTTP Response Headers)
from the business logic layer.
For now there is a crappy EventString which can be passed back to the
controller which can then handle any HTTP related concerns, although long term
these should be actual events like PostPublished or PostUpdated.
This prepares us to return a DTO rather than BookshelfModel to the serialiser
layer. When passing a BookshelfModel, the serialisation layer uses the model to
read from when building computed properties. By stripping values out in the
toJSON method it means that the DTO will be missing them and the computed
properties won't be able to be calculated. Instead we return ALL values to the
serialisation layer, and then strip out the ones that weren't requested in the
"clean" step.
This also inadvertently fixes the issue with `reading_time` requiring the
`html` field to be requested, we can now request just `reading_time`, as well
as have it included by default.
refs https://github.com/TryGhost/Team/issues/3432
The theme images are used directly from admin assets using the admin assets url in AdminX, so these are redundant and not used.
refs https://github.com/TryGhost/Team/issues/3432
- shows user confirmation popup on deleting a theme
- shows user confirmation popup to activate an uploaded theme
- shows user confirmation popup to overwrite an existing theme
refs https://github.com/TryGhost/Team/issues/3432
File upload component was not firing `onChange` when user attempts to upload the same again, which is a side-effect of `input` field behavior. This change resets the file input on every upload with a new key so that the upload always fires
refs https://github.com/TryGhost/Team/issues/3448
Added the ability to specify a description for a custom theme setting
---------
Co-authored-by: Sodbileg Gansukh <sodbileg.gansukh@gmail.com>
refs https://github.com/TryGhost/Team/issues/3423
- When querying for posts that belong to a collection we should be returning full post information just like we do for Posts API.
closes https://github.com/TryGhost/Team/issues/3471
- after adding and removing an icon, icon settings passed an undefined
icon to the signup form's all-in-one style. The AIO conditions didn't
take that into account and caused the entire component to crash.
<!-- Leave the line below if you'd like GitHub Copilot to generate a
summary from your commit -->
<!--
copilot:summary
-->
### <samp>🤖 Generated by Copilot at 9e1aea3</samp>
Fix signup form embed code generation when icon is not set. Add a check
for `this.settings.icon` in `signup-form-embed.js` before replacing
image path.
refs https://github.com/TryGhost/Team/issues/3458
From the discussion in slack, for all published/sent posts:
Published only --> view history & restore
Published & sent --> view history & restore
Email only --> history hidden
And for all unpublished/unsent posts:
All states --> view history & restore.
ref https://ghost.slack.com/archives/C02G9E68C/p1686735066587639
### <samp>🤖 Generated by Copilot at f9ec3e9</samp>
This pull request removes redundant build scripts from the `ghost/i18n`
and `ghost/signup-form` packages. This simplifies the build process and
avoids unnecessary TypeScript compilation.
fixes https://github.com/TryGhost/Team/issues/3473
When a signup happens via the embeddable signup form on your own site, we'll use the default
attribution, so it indistinguishable from a signup via Portal.
closes https://github.com/TryGhost/Team/issues/3471
- after adding and removing an icon, icon settings passed an undefined
icon to the signup form's all-in-one style. The AIO conditions didn't
take that into account and caused the entire component to crash.
<!-- Leave the line below if you'd like GitHub Copilot to generate a
summary from your commit -->
<!--
copilot:summary
-->
### <samp>🤖 Generated by Copilot at 9e1aea3</samp>
Fix signup form embed code generation when icon is not set. Add a check
for `this.settings.icon` in `signup-form-embed.js` before replacing
image path.
fixes https://github.com/TryGhost/Team/issues/3470
- When members are disabled or invite only, the signup form embed should be disabled
- The comments access setting is now also disabled if members are disabled
- The tiers menus are now also disabled if members are disabled