refs MOM-152 MOM-148 MOM-151
- Added Subheads behind a flag + toggle in settings.
- Removes Excerpt fields from post settings if flag is enabled.
- Added subhead toggle in newsletter settings.
- Loads of styling
---------
Co-authored-by: Sanne de Vries <sannedv@protonmail.com>
ref DES-228
This PR updates messaging and error handling in order to make Ghost calmer and friendlier. High level summary of the changes:
- Removed all onBlur validation in Settings -> now it’s possible to just click around without being warned to fill mandatory fields
- Removed lot of technical errors like `ValidationError: Validation (isEmpty) failed for locale`
- Completely removed the red background toast notifications, it was aggressive and raw esp. on the top
- Removed some unnecessary notifications (e.g. when removing a webhook, the removal already communicates the result)
- Now we show field errors on submitting forms, and in case of an error we show a “Retry” button in Settings too. This allowed to remove a lot of unnecessary error messages, like the big error message on the top, plus it’s consistent with the patterns outside Settings.
- Notification style is white now with filled color icons which makes everything much calmer and more refined.
- Removes redundant copy (e.g. "successful(ly)") from notifications
---------
Co-authored-by: Sodbileg Gansukh <sodbileg.gansukh@gmail.com>
closes https://linear.app/tryghost/issue/MOM-97
The 30s search content expiry didn't really make sense and caused unnecessary delays and server load now that search will be more widely used within the editor.
- replaced concept of time-based expiry with explicit expiry
- content still fetched on query if not already loaded or marked as stale
- added `.expireContent()` method on search service to allow explicit expiry
- updated editor to pre-fetch search content when not already loaded or marked as stale
- removes delay when first using internal linking search inside the editor
- updated post model to expire search content on save
- expires on published post save or delete
- expires on publish and unpublish
- updated tag model to expire content on create/save/delete
- only expires when name or url is changed
- updated user model to expire on save/delete
- only expires when name or url is changed
- does not handle creation because that's done server-side via invites
ref MOM61
- Adds admin-x react app we’ll use as ActivityPub playground to the
sidebar nav behind the feature flag.
- Wired up routing to Ember
- Setup the project as `admin-x-activitypub`
---------
Co-authored-by: Ronald Langeveld <hi@ronaldlangeveld.com>
ref
https://linear.app/tryghost/issue/ENG-845/error-attempted-to-set-lexical-on-the-deleted-record
ref
[https://linear.app/tryghost/issue/ENG-854/🐛-deleting-imported-posts-makes-ghost-unresponsive](https://linear.app/tryghost/issue/ENG-854/%F0%9F%90%9B-deleting-imported-posts-makes-ghost-unresponsive)
- When deleting a post in the editor's Post Settings Menu, if the post
has unsaved changes (indicated by the hasDirtyAttributes property in the
editor), Admin will crash because it tries to save a post revision
before leaving the editor, but the post has already been deleted so
saving fails.
- This can occur when editing a post and quickly deleting it from the
Post Settings Menu before saving is completed.
- It can also occur when attempting to delete an imported post, as the
editor will parse the lexical from the server and may make some minor,
invisible-to-the-user changes to the lexical string locally (e.g. JSON
formatting, or updating the JSON to use extended version of base lexical
nodes), which triggers the same error.
- This fix bypasses the attempt to save a post revision when leaving the
editor if the post is already deleted, which allows the transition back
to the Posts route to succeed.
ref 78311591d0
- updated tests to not click a button on the setup/done screen that is no longer shown
- fixed setup flow showing an alert bar due to not handling the `TransitionAborted` error that is thrown by the setup/done->dashboard redirect
refs
https://linear.app/tryghost/issue/IPC-92/add-logic-for-completing-steps
- added `onboarding` service to manage logic and state for the onboarding display and it's various steps
- added basic "display onboarding checklist" state to replicate the basic feature flag toggle along with making sure it's only shown to owners
- added acceptance test file and missing mirage endpoints needed for the dashboard to load without error
refs https://linear.app/tryghost/issue/ENG-599
- member count is based on the cache which only updates ~every minute
- forced cache clear on manual member add/delete (not import)
- tests were failing based on the assumption that a new site that adds a
member has a nonzero member count, although the cache did not reflect
this quickly enough for the test to pass
Previously on a new site if you tried to publish a newsletter, it would
require at least one member. If you quickly added a member and tried to
send a newsletter, it would stop you saying you need at least one
member, requiring a browser refresh. This was a bug that is resolved
with this changes, as well as odd behaviour to try to write tests
around.
no issue
The data generator created an offer for the free product. This caused an
error in admin UI because it couldn't find the tier for the offer.
This fixes the issue in both the data generator and the admin UI.
closes https://github.com/TryGhost/Product/issues/4230
- deleting a post could cause React components to trigger save tasks during teardown which then threw errors because they attempt to set properties on a deleted model instance
- added checks to the `beforeSaveTask()` to abort if the post object has been deleted
closes https://github.com/TryGhost/Product/issues/4228
- when leaving the editor via back button the feature image caption editor's blur handler was called by the React editor component after Ember had torn down the route resulting in an attempt to use `post.set()` when `post` doesn't exist
- the error also caused Lexical to re-render to try and recover which then triggered the blur handler again resulting in an infinite loop
- adding a check to ensure `this.post` exists was enough to fix the problem
refs.
7b40393d77
We're improving the usability and possibilities for publishers to
migrate from other platforms such as Substack, Medium or Mailchimp. This
PR applies changes to Ghost Settings to support the new flows, more
specifically:
- moves import and export functions out of Labs to its own setting,
directly available from search and the menu
- adds direct access to various platform migrations
- moves "Delete all content" to a dedicated setting group at the bottom
of all setting
---------
Co-authored-by: Jono Mingard <reason.koan@gmail.com>
closes https://github.com/TryGhost/Product/issues/4227
- added `@onTKCountChange` to `<KoenigLexicalEditorInput>`
- when present the `isTKEnabled` flag will be turned on and the `<TKCountPlugin>` registered
- added `@registerAPI` support to `<KoenigLexicalEditorInput>` so we can focus the caption editor when its TK indicator is clicked
- added manual display of TK indicator for the caption input
- default editor indicator positioning doesn't work for this input because its container is not full editor width
- hid it by adding `overflow: hidden` to the inner caption container
- added custom indicator button shown when we have a non-zero count
refs https://ghost.slack.com/archives/CTH5NDJMS/p1701688836406919
Deleting members with email disabled, results in deleting all members
due to a broken NQL filter.
The filter `(email_disabled:1)` results in selecting all members because
of the surrounding brackets, which cause a `yg` filter to be generated
by NQL which is not supported by code that handles the Mongo filters.
This is a quick fix to reduce damage, this will need a proper fix in NQL
/ lower level.
refs https://github.com/TryGhost/Product/issues/4184
- set up property on the editor controller for tracking number of TKs, action for updating it, and reset mechanism to ensure we go back to 0 when switching post
- uses random number for now pending `<TkPlugin>` being updated to expose the TK count
- passed TK count data to the publish flow modal so it can show a reminder step before the publish options step when there are still TKs in the post content
- added `onCountChange` prop to `<TkPlugin>` ready for the count feature to be implemented
refs https://github.com/TryGhost/Product/issues/4152
---
<!-- Leave the line below if you'd like GitHub Copilot to generate a
summary from your commit -->
<!--
copilot:summary
-->
### <samp>🤖[[deprecated]](https://githubnext.com/copilot-for-prs-sunset)
Generated by Copilot at a28462f</samp>
This pull request adds a new admin-x app called `admin-x-demo`, which
demonstrates how to use the shared packages `admin-x-framework` and
`admin-x-design-system` to create a simple app that renders a button and
a modal. It also improves the development workflow, the vite
integration, the dependency management, and the type checking for the
admin-x apps and packages. It modifies some files in the
`admin-x-framework` and `admin-x-design-system` packages to make the
modals prop optional, to introduce a new type for the props from the
Ember app, to fix the z-index of the modal backdrop, and to use
consistent file extensions and module syntax.
fixes https://github.com/TryGhost/Product/issues/3738https://www.notion.so/ghost/Member-Session-Invalidation-13254316f2244c34bcbc65c101eb5cc4
- Adds the transient_id column to the members table. This defaults to
email, to keep it backwards compatible (not logging out all existing
sessions)
- Instead of using the email in the cookies, we now use the transient_id
- Updating the transient_id means invalidating all sessions of a member
- Adds an endpoint to the admin api to log out a member from all devices
- Added the `all` body property to the DELETE session endpoint in the
members API. Setting it to true will sign a member out from all devices.
- Adds a UI button in Admin to sign a member out from all devices
- Portal 'sign out of all devices' will not be added for now
Related changes (added because these areas were affected by the code
changes):
- Adds a serializer to member events / activity feed endpoints - all
member fields were returned here, so the transient_id would also be
returned - which is not needed and bloats the API response size
(`transient_id` is not a secret because the cookies are signed)
- Removed `loadMemberSession` from public settings browse (not used
anymore + bad pattern)
Performance tests on site with 50.000 members (on Macbook M1 Pro):
- Migrate: 6s (adding column 4s, setting to email is 1s, dropping
nullable: 1s)
- Rollback: 2s
refs https://github.com/TryGhost/Product/issues/4055
---
<!-- Leave the line below if you'd like GitHub Copilot to generate a
summary from your commit -->
<!--
copilot:summary
-->
### <samp>🤖 Generated by Copilot at 3b24693</samp>
Removed unused components related to announcement settings, custom theme
settings, and file upload. These components were part of a deprecated
feature or a legacy UI.
refs https://github.com/TryGhost/Ghost/pull/18816
When opening a new post in the editor and immediately leaving we would hang because we attempted to save a revision rather than just throwing the blank post away.
- added additional `hadDirtyAttributes` check to the forced-revision save when leaving
- added additional destroyed post checks to the save task to avoid saving a deleted post when leaving the editor
- removed unnecessary waits for save tasks that prevented leaving the editor when the title on a new post had been filled in but not saved (matches previous editor behaviour)
closes https://github.com/TryGhost/Product/issues/4059
- modified `saveTask` so when it has the `leavingEditor` option it doesn't attempt to set a new post status
- save when leaving the editor is never a publish/unpublish-related event, rather it's a convenience autosave and a forced revision creation so modifying the post status should never happen for those saves
- updated the `willTransition` handling to avoid repeated saves
- sets a property on the controller whenever we attempt a save+transition retry on leaving the editor then skips any further attempted saves on transitions
- although it would be preferable we can't use `try/catch` on these saves because our save task always catches and doesn't re-throw, adjusting that would be a much larger change than we want to make for this fix
no issue
- removed labs flag
- removed main editor component and all associated components
- switched usage of `<KoenigBasicHtmlInput>` and `<KoenigBasicHtmlTextarea>` over to use plain `textarea`, the only uses were in settings modals that have been replaced in AdminX
- cleaned up unused editor CSS
refs TryGhost/Product#4022
- This block of code converts any snippets that are only in mobiledoc to lexical locally in the editor, then sends a PUT request for each snippet to update it on the server
- For sites with > 50 snippets, these PUT requests were triggering rate limits on Pro of 50 req/s
- This change is a temp fix to add a 100ms sleep between these requests to stay under the 50 req/s limit
- Longer term, we may introduce a migration that will convert all snippets, or modify the editor to somehow lazily convert the snippets when needed, but this temp fix should resolve the rate limiting issue for the time being
refs TryGhost/Product#3510
- Added `TryGhost/Source` as a submodule in `ghost/core/content/themes` so `Source` will ship with Ghost (along with Casper)
- With this change, new installs will use `Source` as the default theme. Existing sites will have `Source` installed, but not activated, as this is a large change and we don't want to drastically change existing sites without warning. Users can upgrade to use `Source` simply by clicking 'Activate' in design settings.
- Updated protections to prevent users from uploading their own conflicting version of `Source`
no issue
- we don't want accidental background clicks closing this modal as it contains complex UI rather than a simple notification
- the members import modal is still using the old/outdated modal pattern so there was no option for disabling background click, went with a quick-fix for now rather than updating everything to our modern modal patterns
- added passthrough of arguments to the `close` action on `<GhFullscreenModal>`
- updated `<GhFullscreenModal>` background click handler to pass "background" as an action argument
- updated the action used for handling members import modal closing to skip closing when it receives "background" as the first argument
refs https://github.com/TryGhost/Product/issues/3843
If you used relative URLs in the beta editor, when it came to leaving the editor you would get stuck due to an infinite save loop occurring in the background requiring a refresh to get back to a working state.
- when saving relative URLs the server will convert them to absolute for consistency and to ensure URLs work in other situations such as emails, RSS, 3rd party editors, etc
- although we get different data back from the server we don't overwrite the content in the editor with it as that would cause loss of changes since the save as well as loss of the cursor position
- when leaving the editor we compare content from the last save revision with the current editor content to see if we need to save a new revision but if the server data has been modified with relative->absolute URLs then we'd enter an infinite loop because the content would never match
- relative->absolute URLs should be the only thing to ever be modified in the underlying data when saving so we can work around the issue by replacing each instance of the site's URL before comparing revision data to current data
reverts TryGhost/Ghost#17912
- unfortunately dropping save tasks when one is already running has side-effects for code that is initiating the save tasks
- e.g. the slug or title update actions call `saveTask.perform()` and if that related save request fails they expect to get a standard request error so they can show a message and perform a model rollback. However with `keepLatest` the save task can be dropped and "fail" immediately with a `TaskCancelation` error which has unintended side-effects:
1. error handling is no longer tied to the specific request meaning we could have slug-related failures being handled by non-slug-save code which is unexpected
2. the internal `TaskCancelation` error is handled as if it was general error and we end up showing a useless error in the red error bar that makes it look like something failed when it didn't
3. we initiate a model rollback when we do not have a failure situation that requires it meaning we can lose changes
no issue
- adds explicit waits for the two save tasks when leaving the editor before any other checks or saves are triggered
- cleans up some errors around task cancellation that could be triggered when leaving the editor with an existing save running
no issue
- when a post is new it has no revisions but in the `willTransition` hook we were using `lastRevision.get` even though `lastRevision` was null
- adjusted the `hasChangedSinceLastRevision` conditional to always be `false` for new posts
no issue
- every triggered save was being added to a queue resulting in an unnecessary number of requests in some circumstances because it means every triggered save would be run sequentially even though the intermediate saves could be safely thrown away if we're still waiting on a response to a previous one
- switched from a standard queue to ember-concurrency's `keepLatest` behaviour
- drops intermediate saves if multiple saves are triggered whilst still waiting on a previous save
- http://ember-concurrency.com/docs/task-concurrency#keepLatest
closes https://github.com/TryGhost/Product/issues/3735
The member newsletter filter was not working correctly when multiple
filters were applied due to the regex incorrectly extracting the
contents of a grouped filter. This commit splits the regex into two to
make it easier to reason about and fixes the underlying issue
no issue
- added some more info to the comment
- found the actual issue that needed the admin p0 fix last night.
Updated the comment info block with a link to that issue.
<!-- Leave the line below if you'd like GitHub Copilot to generate a
summary from your commit -->
<!--
copilot:summary
-->
### <samp>🤖 Generated by Copilot at bcec294</samp>
Updated a comment in `members.js` to link to a possible NQL issue. This
helps explain the temporary fix for filtering members by labels with
parentheses.
refs https://ghost.slack.com/archives/CTH5NDJMS/p1692021848890629
- Addresses an NQL / API edge case where standalone filters with
parentheses doesn't get handled correctly within bulk operations such as
member labelling, member unsubscribe and member deletion.
- This is currently only affected by newsletter related filters.
- This adds a regex functions that checks when those filters are used
and removes the parentheses when required.
- Ideally we fix the NQL / API issue in the near future and remove this
regex hack altogether, but taking all things into consideration, this
should mitigate the risk of potential data-loss for Ghost users.
closes https://github.com/TryGhost/Product/issues/3719
- adds Sentry reporting for slow saves in the editor to help investigate reports of a similar nature
- uses different messages for lexical vs mobiledoc and successful vs failed saves so we can compare frequency of each in the Sentry UI
- includes `save_time` tag so we can see a breakdown of timings and adjust the threshold if necessary
- includes `post_type` tag which will be useful as we introduce further differences between the features and rendering cycle of posts and pages
- includes `newsletter` and `email_segment` tags to help indicate if slow saves are due to email sending
- includes `save_revision` tag to help indicate if forced revision saves cause slow saves
- includes `convert_to_lexical` tag to help indicate if mobiledoc/lexical conversion is causing slow saves
closes https://github.com/TryGhost/Product/issues/3604
- The change password button in the user settings wasn't updating correctly.
- the saveNewPasswordTask() wasn't returning anything, causing `
this.get('task.last.value')` to return undefined in the `isSuccess`
method.
- This fix ensures that there is a value attached to the
`task.last.value` so that the condition for a successful save checks
out.
---
<!-- Leave the line below if you'd like GitHub Copilot to generate a
summary from your commit -->
<!--
copilot:summary
-->
### <samp>🤖 Generated by Copilot at a6a76eb</samp>
Improved error handling and feedback for changing user passwords in the
settings UI. Modified `saveNewPasswordTask` function in
`ghost/admin/app/controllers/settings/staff/user.js` to catch and
display errors and return user object.
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)