Skip to content

✨ Implemented duplicate post functionality#16767

Merged
mike182uk merged 5 commits intoTryGhost:mainfrom
mike182uk:duplicate-post
May 15, 2023
Merged

✨ Implemented duplicate post functionality#16767
mike182uk merged 5 commits intoTryGhost:mainfrom
mike182uk:duplicate-post

Conversation

@mike182uk
Copy link
Copy Markdown
Member

refs: https://github.com/TryGhost/Team/issues/3139 https://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/

@codecov
Copy link
Copy Markdown

codecov bot commented May 10, 2023

Codecov Report

Patch coverage: 100.00% and project coverage change: +28.54 🎉

Comparison is base (080a1c9) 56.17% compared to head (15191f8) 84.72%.

Additional details and impacted files
@@             Coverage Diff             @@
##             main   #16767       +/-   ##
===========================================
+ Coverage   56.17%   84.72%   +28.54%     
===========================================
  Files        1695      692     -1003     
  Lines      105839    53588    -52251     
  Branches    12249     6864     -5385     
===========================================
- Hits        59456    45402    -14054     
+ Misses      45272     8115    -37157     
+ Partials     1111       71     -1040     
Flag Coverage Δ
e2e-tests 84.72% <100.00%> (?)
unit-tests ?

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
ghost/core/core/server/api/endpoints/pages.js 100.00% <100.00%> (ø)
ghost/core/core/server/api/endpoints/posts.js 100.00% <100.00%> (ø)
...ver/api/endpoints/utils/serializers/input/pages.js 91.34% <100.00%> (+12.24%) ⬆️
...ver/api/endpoints/utils/serializers/input/posts.js 97.42% <100.00%> (+11.58%) ⬆️
...core/core/server/web/api/endpoints/admin/routes.js 100.00% <100.00%> (ø)

... and 1647 files with indirect coverage changes

☔ View full report in Codecov by Sentry.
📢 Do you have feedback about the report comment? Let us know in this issue.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm slightly cautious when using omit in code as it hides additional maintenance long-term. For example, when we add a new field to the posts table we'd have remember to exclude it here too if it's a field we don't want to copy over. On the other hand, we'd get a failure for the snapshot test and would need to update it, so there is some signal for us to check on this list in the future. What are your thoughts on this @mike182uk ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeh I had the same thought - Inversely you end up with the same problem when you pick the fields you want - If a new field is added that needs to be copied over, you would need to update the list (or manually set the value on the model etc.) - It felt more likely that there would be less fields that need excluding than need including (which would ease maintenance burden), but yeah either way the snapshot test should flag that there is data mismatch

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a cleaner way to pass this information would be allowing for a custom option in the endpoint definition itself. Checking for method names in the framework gives a code smell tbh. 🤔

We could introduce something like frame.location and determine the returned header base on the value there, this way we would not create additional coupling between framework and method names inside of endpoint definitions.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeh i get what your saying with this - Looking at it, I think this might be better done as a refactor afterwards instead of part of this PR? If we remove the method check, we would need to go through all of the controllers and provide someway of letting this logic know it needed to generate the location header

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't have to go throught all controllers, just check if the new config value is present than use it and if not leave the previous logic as is.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See what you think to 15191f8 👍

Copy link
Copy Markdown
Contributor

@naz naz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a good direction and I think we are 99% there just a few minor tweaks we'd need to do. Great job Mike 🚀

mike182uk and others added 5 commits May 11, 2023 15:11
refs: TryGhost/Product#3139 TryGhost/Product#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 TryGhost/Product#3179

- updated the post duplication icon
- added a separator between the non-destructive and destructive actions
- improved icon consistency
const locationHeaderDisabled = apiConfigHeaders?.location === false;
const hasFrameData = ['add', 'copy'].includes(frame?.method) && result[frame.docName]?.[0]?.id;
const hasLocationResolver = apiConfigHeaders?.location?.resolve;
const hasFrameData = (frame?.method === 'add' || hasLocationResolver) && result[frame.docName]?.[0]?.id;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yessss! No additional hardcoded method in the framework layer and gives us a clear path of migration to move away from hardcoded add when we find appetite for it 👍

Copy link
Copy Markdown
Contributor

@naz naz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The copy post feature is good for prime time :shipit:

@mike182uk mike182uk merged commit 59fe794 into TryGhost:main May 15, 2023
@mike182uk mike182uk deleted the duplicate-post branch May 17, 2023 20:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants