refs https://github.com/TryGhost/Team/issues/3151
- adds route in Admin for opening new settings screen in react
- adds new config for passing `adminX` to Admin
- loads adminX settings from package in Admin UI when new route is opened
Co-authored-by: Peter Zimon <zimo@ghost.org>
refs https://github.com/TryGhost/Team/issues/3151
- adds a new vite + typescript + storybook + TW package for setting up admin settings in react with base config that works with Ghost monorepo
- includes base components/design system for new settings UI
- adds eslint rule config to the package to match rest of Ghost codebase
- this is an experimental package as we figure out the best patterns for new admin packages in Ghost monorepo
Co-authored-by: Peter Zimon <zimo@ghost.org>
closes https://github.com/TryGhost/Team/issues/3166
- The collections service contains CRUD logic to manage collection entities through: save, getById, getAll, and destroy methods.
closes https://github.com/TryGhost/Team/issues/3219
- the pages template had a leftover .gh-list-sticky and it was causing an additional scrollbar inside the list
- removing the unncessary element fixes the issue
refs TryGhost/Team#3213
---
<!-- Leave the line below if you'd like GitHub Copilot to generate a
summary from your commit -->
<!--
copilot:summary
-->
### <samp>🤖 Generated by Copilot at 2a96438</samp>
This pull request enhances the feedback modal feature in the lexical
editor. It improves the layout and appearance of the modal and its
trigger button, and uses a dropdown component to show and hide the
modal.
closes https://github.com/TryGhost/Team/issues/2950
- when adding/editing tiers, benefits used to be added only when the plus button was pressed
- this adds enter key support for adding new benefits, same as how the navigation items are added
refs: https://github.com/TryGhost/Team/issues/3139https://github.com/TryGhost/Team/issues/3140
- Added duplicate post functionality to post list context menu
- Currently only a single post can be duplicated at a time
- Currently only enabled via the `Making it rain` flag
- Added admin API endpoint to copy a post - `POST ghost/api/admin/posts/<post_id>/copy/`
- Added admin API endpoint to copy a page - `POST ghost/api/admin/pages/<page_id>/copy/`
refs https://github.com/TryGhost/Team/issues/3172
The outbound link tagger was tagging non http urls (i.e `javascript:`,
`mailto:`) which would prevent these urls from working as expected. This
change only allows urls to be tagged if they use the `http(s)` protocol.
refs https://github.com/TryGhost/Team/issues/2616
- long urls were causing scrolls in the members activity
- now the urls are broke into multiple lines, so that it's easier to understand/copy them
We had side stepped the existing checks of lexical and the feature flag when
checking if a published post was sent as an email. This takes into account the
existing checks to make sure the feature isn't leaked without the flag
refs https://github.com/TryGhost/Toolbox/issues/515
Tiers are very frequently queried and we want to reduce the number of DB calls
we're making. We can store the Tiers in-memory, using the existing in-memory
repository patterns, but still persisting writes the the database.
We also have to update our test helpers, because they were bypassing the
repository for writes, but using it for reads resulting in an invalid cache
We want to cache access to Tiers, and it's easier to do that in the
TierRepository. So we update a heavy user of Tiers to use the Tier
service so it can take adv of caching. The serializers are a big
offender for making calls to fetch Tiers.
- this dependency seems a pretty heavy one to require upon boot and
given most sites don't need it to function as normal, this saves
several MB of RAM per instance
closes https://github.com/TryGhost/Team/issues/3176
We were waiting for the welcome email to send before responding to the
client that setup is complete, this was causing the client to hang when
running `ghost install local` as mail isn't configured by default.
no issue
- the lexical lib file makes use of `jsdom` but there was no explicit dependency for it in `package.json` meaning we were relying on it being incidentally depended on through another package which is brittle
no refs
- add lexical feedback modal in the editor, labs, and publish workflows
- modal is a basic textarea form
---------
Co-authored-by: Djordje Vlaisavljevic <dzvlais@gmail.com>
refs: https://github.com/TryGhost/Team/issues/2390
Escapes each matched and non-matched segment of the post title in the
admin search field, to make sure they're displayed in plain text but
still have matches highlighted.
These versions use the latest version of @tryghost/errors, which uses
the correct import for @stdlib/utils-copy. This should hopefully stop
missing module errors when running locally.
This is the first pass at an abstract class for our in-memory repository
implementations. It's based off of the existing implementations and
should speed up local development and deduplicate code
refs https://github.com/TryGhost/Team/issues/2619
- blur event occurs before mouseup event is called, so when the update button was clicked, the update function has never been called in Safari
- this replaces the mouseup with mousedown which is called before the blur event, so the links are updated properly
We were incorrectly specifying the path of the file rather than relying on the
package exports, and this broke in the previous commit to a file rename. It
wasn't caught by CI because the browser tests are not run on pull requests
As discussed with the product team we want to enforce kebab-case file names for
all files, with the exception of files which export a single class, in which
case they should be PascalCase and reflect the class which they export.
This will help find classes faster, and should push better naming for them too.
Some files and packages have been excluded from this linting, specifically when
a library or framework depends on the naming of a file for the functionality
e.g. Ember, knex-migrator, adapter-manager
no issue
This pull request adds a new experimental feature flag `signupCard` to
the Ghost admin app, which enables a signup card component in the
lexical editor that's currently being worked on.
The feature flag can be toggled from the settings/labs
UI and is read from the server-side configuration.
Whilst Admin API Integrations had the permissions to create invites they were
blocked from doing so at the HTTP level. We've removed this restriction for
creating Invites as well as browsing Roles, because a Role ID is necessary to
create an invite. The code was also not setup to support Admin API Integrations
as it made assumptions about the existence of a User. That has been updated in
the permissions layer - so that the Invites are limited to Contributors,
Authors and Editors as well as at the email layer, which has has the copy and
from address updated to reflect the lack of a User creating the Invite.
We only display the signup checkbox if both the checkbox is required AND we
have some terms to display alongside it. However we require the checkbox to be
checked, regardless of if it is displayed. This results in the Signup button
not working at all if your settings are in this state.
refs https://github.com/TryGhost/Team/issues/3145
- includes image editing for generic upload image components to extend
image editing capabilities to other areas in Admin
- allows image editing for tag images and staff user images
refs 9d104c8511
- we've seen recurring instances where Ghost will hog memory after image
uploads
- we use `jemalloc` to try and help this, but it still seems to happen
- according to the sharp thread referenced in my commit above, memory
fragmentation can also be helped by reducing the concurrency within
sharp
- this is a bit of an experiment and we can revert if it causes issues
refs TryGhost/Team#3147
---
<!-- Leave the line below if you'd like GitHub Copilot to generate a
summary from your commit -->
<!--
copilot:summary
-->
### <samp>🤖 Generated by Copilot at 7dfd8bf</samp>
This file adds a function to clean and format the HTML of the
`koenig-lexical-editor-input` component and passes it to the
`HtmlOutputPlugin` component.
no issue
This commit removes the `memberAttribution` feature flag from the
codebase. Some CSS classes are not removed as removing them and updating
the associated CSS files have side effects sadly.
- I switched over `build` to run in production mode because we now do
`lerna run build` during the release process, but this was bundling
development assets
- this adds `build:dev` and switches the browser test to use that, so
they should use the development assets moving forwards
refs TryGhost/Team#3122
<!-- Leave the line below if you'd like GitHub Copilot to generate a
summary from your commit -->
<!--
copilot:summary
-->
### <samp>🤖 Generated by Copilot at 87727d9</samp>
Added `data-testid` attributes to various elements in the announcement
bar settings feature to enable Playwright testing. Fixed a potential bug
with the `visibilitySettings` getter in the `visibility.js` component.
Added Playwright tests for the announcement bar settings feature in
`announcement-bar-settings.spec.js`.
refs 27e4523aec
- we no longer use `oembed-parser`, so we can remove it from
package.json
- also pins the `@extractus/oembed-extractor` package and adds it into
`@tryghost/oembed-service` where it was missing
no issue
The post/page bulk actions weren't logged in the history log / actions
table.
This change adds support for logging bulk actions.
- New `addActions` static method on models. It creates an action log in
the database for multiple models at once. If only one model was edited,
deleted or added, it will fallback to `addAction`
- `addAction` can also be called statically now
- `actionName` option is now supported when using `addActions`,
`addAction`, and as a result also in all bulk manipulation methods, and
CRUD methods. This allows you to replace the default '5 posts edited'
into something more specific like '5 posts featured'
- Fixed support for null resource_id in the parse-history-event helper
- Removed the default 'published' status requirement when using
Post.findOne for internal queries.
refs TryGhost/Ghost#16048
- When attempting to embed a Youtube video that has had embedding
disabled by its owner/author, Ghost displayed a generic error message
that didn't indicate the reason for the failed emebed.
- This change updated the error message when Youtube (or any provider)
returns 401: Unauthorized to indicate that the owner of the resource has
explicitly disabled embedding.
no issue
This pull request removes the `suppressionList` feature flag and all its
dependencies from the codebase. It makes the suppression list feature
the default and consistent behavior for all email events and
newsletters. It simplifies the UI, logic, and data related to email
events and newsletters. It affects several files in the
`ghost/admin/app`, `ghost/core/core`, and `ghost/members-api`
directories.
fixes https://github.com/TryGhost/Team/issues/2404
This change introduces a new 'post' query parameter to the members and member routes.
Previously, the members route would check if the previous route was the analytics page, and then show the breadcrumbs to go back to the analytics page. But when navigating to the members page from the menu, we don't want to show the breadcrumbs. To accomplish this, the routes that point to the members page from the analytics page now specifically pass on the post id in the query parameters. The query parameter is then passed on from the members page to the member page.
`directlyFromAnalytics` is still used in the member route, to know wheter we came from the members page or from the analytics page (changes the breadcrumbs). This doesn't need to go via a query parameter (figured that would make the url too long/complex).
The resetController method is now implemented and resets the filter and/or fromAnalytics post id if required (when going from members to member, we don't want to reset it because the we would lose the filter going back).
refs TryGhost/Team#3133
- the backend previously had logic to save a revision if more than 10
mins had elapsed since the last revision
- however, the frontend would autosave after 3 seconds of inactivity
(which doesn't trigger a revision), and never send another save request
at 10 minutes, so the backend logic to save a revision was never
triggered
- this change will save the current contents of the editor every 10
minutes, even if nothing has changed since the last save
This is an initial start to using TypeScript in our non-core Ghost packages.
- Adds a prepare script to build the project after installing deps
- Adds an initial tsconfig.json which is compatible with our node env
- Migrates all of the code to TypeScript, including tests
- Updates tests to use ts-node so that we don't need to compile the tests
- ts-node is installed at the top level because the env is weird with lerna and
doesn't work otherwise
- Updates the yarn dev script to build the project with the --all and --revisions flag
- Updates the prepare script in the top level to run prepare on packages, so
that packages can be built when running `yarn`
- Updates the build script in ghost/core to run build on packages, so that
packages are built before being monobundled
- Updates monobundle to be a dependency and use the new TryGhost repo, which
includes some minor fixes and improvements, such as supporting devDeps
- Updates the GitHub workflows to run the build command in the top level
directory rather than ghost/core so that other packages are built, too.
refs https://ghost.slack.com/archives/C025584CA/p1683105468216909
When holding cmd,ctrl or shift when clicking a post list item, it would try to select it. But that meant some user flows were broken where users would open multiple posts at the same time in a new tab.
This change allows you to cmd/ctrl/shift/right click on the edit button again.
refs https://github.com/TryGhost/Ghost/security/advisories/GHSA-r97q-ghch-82j9
Because our filtering layer is so coupled to the DB and we don't generally
apply restrictions, it was possible to fetch authors and filter by their
password or email field. Coupled with the "starts with" operator this can be
used to brute force the first character of these fields by trying random
combinations until an author is included in the filter. After which the next
character can be brute forced, and so on until the data has been leaked
completely.
refs https://github.com/TryGhost/Ghost/security/advisories/GHSA-r97q-ghch-82j9
Because our filtering layer is so coupled to the DB and we don't generally
apply restrictions, it was possible to fetch authors and filter by their
password or email field. Coupled with the "starts with" operator this can be
used to brute force the first character of these fields by trying random
combinations until an author is included in the filter. After which the next
character can be brute forced, and so on until the data has been leaked
completely.
no issue
There was an error when generating the snapshot for this test. It never ran, so the snapshot was never committed. On top of that, the generated snapshot would change every time because the email verification token was not replaced with a static value.
closes https://github.com/TryGhost/Team/issues/3137
We have now included the ability to display an "Unpublished" tag for revisions that have been unpublished. The tag is only displayed when the revision's reason property is set to "unpublished". A new revision is triggered when a post is unpublished, regardless whether there's a change in the content.
refs https://github.com/TryGhost/Team/issues/3129
This has copied the same pattern from the gh-user-list-item component.
Co-authored-by: Sanne de Vries <sannedv@protonmail.com>
fixes https://github.com/TryGhost/Team/issues/2385
The Sentry version has been locked to v7.11.1 for some time because Sentry still used a legacy Node feature, called domains. Due to a bug or change in in Noide 16+, those domains broke handling uncaught promise execptions. So Ghost crashed when a promise exception wasn't caught. But that shouldn't be the case because we have a global uncaught exception handler.
Luckily Sentry switched to AsyncLocalStorage in v7.48.0. This fixes the issue as demonstrated in c0cd62184c
no issue
- Hide post preview select if there is no published posts yet.
---
<!-- Leave the line below if you'd like GitHub Copilot to generate a
summary from your commit -->
copilot:summary
- we have calls to the metrics library so we can measure the time it
takes the Mailgun API to return a response
- however, there's a bug in the code whereby if the `batchHandler`
takes a long time and then throws an error, this time will be reported
to metrics
- this is misleading because it looks like Mailgun is taking a long time
if the databases are slow
- this pulls the specific SDK call out into a function so it's easier to
wrap with timing code
refs https://ghost.slack.com/archives/C02G9E68C/p1682941387256079?thread_ts=1682507718.761429&cid=C02G9E68Chttps://github.com/TryGhost/Team/issues/3123
This commit modifies the revisionList method to sort the revisions array by createdAt property in descending order, instead of reversing the order of the array. This makes the code more intuitive and easier to follow for future developers.
Additionally, the published_latest key-value pair is renamed to initial_publish to better reflect its meaning. This key-value pair is added to the revision object at the index where the post status changed from 'draft' to 'published', indicating the initial publication of the post.
refs https://github.com/TryGhost/Team/issues/3123
This commit modifies the revisionList method to add a new key-value pair published_latest: true to the object if the current index matches with the index of the latest published revision with the reason 'published'. The change only affects the latest published revision and doesn't modify any existing data. This update improves the display of post revisions by highlighting the latest published revision in the list.
refs TryGhost/Team#3122
- Fixed that preview takes data from user input before saving on
backend.
---
<!-- Leave the line below if you'd like GitHub Copilot to generate a
summary from your commit -->
<!--
copilot:summary
-->
### <samp>🤖 Generated by Copilot at 54d5b2d</samp>
This pull request adds the ability to preview the announcement bar in
the Ghost admin panel and the theme settings. It also adds a
confirmation dialog to discard or save unsaved changes before leaving
the announcement bar settings. It refactors some components and methods
to remove unnecessary or redundant calls to save the settings. It
modifies the `ghost_head` helper, the `theme-management` service, and
the `announcement-bar/src` files to support the preview feature.
https://github.com/TryGhost/Team/issues/3121
- Because the announcement data has to be available with member's context, it's only possible to have it in cross-origin requests in the Members API.
- Exposed the announcement bar data through `GET /members/api/announcement` endpoint
no issue.
- In dark mode the text and the text selection color in the announcement bar's input field were the same. This made the selected text unreadable
refs. https://github.com/TryGhost/Team/issues/3112
- the font color in the announcement input field was not prepared for dark mode
- the first background swatch had an unwanted border setting
no issue
After making a change to a post via the bulk action menu, the filter checks if the post should still be included on the page. If not, it is removed.
There were two bugs here:
- Expansions were not applied
- Relation checks were not working because the model was not serialized
Now the posts correctly stay on the page if needed, or are removed if not.
refs https://github.com/TryGhost/Team/issues/3112
- When members features are disabled on the site, there is no point to show member-specific filters for the announcement bar. The only option available should be to show or not to show the announcement.
refs https://github.com/TryGhost/Team/issues/3010
- Having all possible values in within single packages will make it easier to look for "source of truth" and is more maintainable rather than having values scattered all over the codebase
refs https://github.com/TryGhost/Team/issues/2887
Images could sometimes be pasted into the editor (noticed especially with Google Docs) with `data:` URLs rather than typical `https:` URLs. That causes problems because data URLs are large binary blobs that get stored in the `posts` table and passed through many areas of the system that doesn't expect large binary blobs, causing knock-on effects.
- added handling to our editor's image card to detect when the card is displayed in the editor with a `data:` URL and if it was then it converts it to a file and uploads it so the image can be stored and displayed the same way as any other image
- handles uploads on both paste and opening a post in the editor that was previously saved with a `data:` URL
We no longer need a reference to the previous version, instead we can use the
latest revision, this makes it easier to compare "off table" data such as the
feature image caption stored in posts_meta.
no 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 ebd1973</samp>
This pull request adds support for storing and tracking the status of
posts in revisions. It introduces a new `post_status` column and
property in the `post` and `PostRevision` models, and updates the
`PostRevisions.formatInput` method to handle it.
refs https://github.com/TryGhost/Team/issues/3051
- The filter was not working properly when there was no logged in member, but the announcement filter was set to "paid_members" only
refs TryGhost/Team#3095
We should show the announcement bar again in the following case:
- User closes the bar
- Publisher updates announcement content
- We show the bar again even if the user closed it previously in the
same session
refs https://github.com/TryGhost/Team/issues/3104
When a post revision author has been deleted, or there is no author
associated with a post revision, the label "Anonymous" is used for the
revision author
refs https://github.com/TryGhost/Team/issues/3099
<!-- Leave the line below if you'd like GitHub Copilot to generate a
summary from your commit -->
<!--
copilot:summary
-->
### <samp>🤖 Generated by Copilot at 83140b5</samp>
This pull request adds a new column `post_status` to the
`post_revisions` table to store the status of the post revision. It also
updates the schema definition, the migration file, and the integrity
test to reflect the new column.
refs https://github.com/TryGhost/Team/issues/3102
Post revision restoration was failing due a few failing edge cases that
occurred during the refactor of the post history modal
refs @TryGhost/Team#3076
- added `save_revision` option to edit post endpoint
- this change covers the following cases:
1. we will not save a `post_revision` on every background autosave that
occurs after 3 seconds of inactivity in the editor
2. we will save a `post_revision` when the user hits `cmd+s` in the
editor to explicitly save
3. we will save a `post_revision` when the user navigates away from the
editor (e.g. by clicking the 'Posts' breadcrumb in the editor)
4. we will save a `post_revision` when the user publishes a post
5. we will save a `post_revision` when a user updates an already
published post
closes https://github.com/TryGhost/Team/issues/3077
<!-- Leave the line below if you'd like GitHub Copilot to generate a
summary from your commit -->
<!--
copilot:summary
-->
### <samp>🤖 Generated by Copilot at 27c2916</samp>
This pull request refactors the modal-post-history component from a
classic Ember component to a glimmer component, using the latest APIs
and syntax. This improves the code quality and aligns with the Octane
edition of Ember. The changes affect the
`ghost/admin/app/components/modal-post-history.js` and
`ghost/admin/app/components/modal-post-history.hbs` files.
refs https://github.com/TryGhost/Ghost/pull/14264
- With a requirement change we need to transform `announcement_visibility` setting to be an "array" instead of a "string". Array structure will allow us to hold multiple filters at once giving more coverage to the audience targetting usecases.
- Example filter variations we'll support are:
[ ] Logged out visitors
[ ] Members
[ ] Free members
[ ] Paid members
refs https://github.com/TryGhost/Team/issues/3034
- adds new integration page for Pintura in Admin
- allows site owners to enable/disable the image editor integration
- allows self-hosters to upload the files for enabling Pintura image
editor
---------
Co-authored-by: Sodbileg Gansukh <sodbileg.gansukh@gmail.com>
refs https://github.com/TryGhost/Team/issues/3034
- adds 3 new settings for managing pintura image editor integration in
admin
- `pintura` setting controls the enabling of the feature
- `pintura_css_url` is used to store path to pintura css file uploaded
on integration page
- `pintura_js_url` is used to store path to pintura js file uploaded on
integration page