Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate to Strapi 5 (pre-release) #146

Merged
merged 22 commits into from
Dec 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
0eecb9e
Update package and gitignore and remove unnecessary files
mattmilburn Nov 30, 2024
708de27
Upgrade all dependencies and use ^ ranges everywhere
mattmilburn Nov 30, 2024
b3ec0b5
Minor fixes and formatting across several files
mattmilburn Dec 2, 2024
2afbf5b
Update eslint config for Typescript
mattmilburn Dec 2, 2024
b664041
Update lint-staged config
mattmilburn Dec 2, 2024
c0bacc2
Refactor for jest and typescript testing
mattmilburn Dec 3, 2024
c405dc3
Downgrade certain packages to a version compatible with Strapi
mattmilburn Dec 4, 2024
9e320bf
Fix plugin id
mattmilburn Dec 5, 2024
7912507
Update method of type imports
mattmilburn Dec 6, 2024
a5039f4
Upgrade strapi deps to 5.5.0
mattmilburn Dec 10, 2024
7a250c6
Rename unstable hook import
mattmilburn Dec 10, 2024
ae0b365
Update README and MIGRATION docs
mattmilburn Dec 10, 2024
d051ca3
Fix import for useStrapiApp
mattmilburn Dec 11, 2024
7e7be6c
Remove supertest and sqlite3
mattmilburn Dec 11, 2024
6a36952
Refactor how list view column is rendered, including lang updates
mattmilburn Dec 11, 2024
44fd312
Render draft and published buttons only on their tab views
mattmilburn Dec 11, 2024
cac6f4b
Add support for locale
mattmilburn Dec 11, 2024
00ebaac
Refactor button visibility based on new draft published system
mattmilburn Dec 12, 2024
da5cdb7
Update README and screenshots
mattmilburn Dec 13, 2024
ae416ab
Use style components for button styles
mattmilburn Dec 13, 2024
bc7616b
Add uid prop to compileWithHooks
mattmilburn Dec 13, 2024
ff39b67
Add type for hook props
mattmilburn Dec 13, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions .eslintignore

This file was deleted.

1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,3 @@ yarn-error.log
############################

coverage
junit.xml
3 changes: 0 additions & 3 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Testing
/coverage
junit.xml

# Misc
.DS_Store
Expand All @@ -15,6 +14,4 @@ yarn-error.log*
.editorconfig
.eslint*
.prettier*
.yarnrc.yml
yarn.lock
jest.config.js
1 change: 0 additions & 1 deletion .npmrc

This file was deleted.

1 change: 0 additions & 1 deletion .yarnrc.yml

This file was deleted.

6 changes: 6 additions & 0 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,17 @@

## Get Started

* [Migrate from v2 to v3](#migrate-from-v2-to-v3)
* [Migrate from v1 to v2](#migrate-from-v1-to-v2)
* [Migrate from v0 to v1](#migrate-from-v0-to-v1)

---

## <a id="migrate-from-v2-to-v3"></a>Migrate from v2 to v3
This upgrade requires Strapi v5 and is NOT compatible with Strapi v4.

Everything else with your plugin installation can remain the same.

## <a id="migrate-from-v1-to-v2"></a>Migrate from v1 to v2
The breaking changes in this migration focus on improving plugin options and also a simple find and replace for a parameter name in the `before-build-url` hook.

Expand Down
152 changes: 57 additions & 95 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,29 @@
<img style="width: 160px; height: auto;" src="public/logo-2x.png" alt="Logo for Strapi preview button plugin" />
<h1>Strapi Preview Button</h1>
<p>A plugin for Strapi CMS that adds a preview button and live view button to the content manager edit view.</p>
<p>
<a href="https://www.npmjs.com/package/strapi-plugin-preview-button">
<img src="https://img.shields.io/npm/v/strapi-plugin-preview-button.svg" alt="Latest npm version" />
</a>
<a href="https://strapi.io">
<img src="https://img.shields.io/badge/strapi-v5-blue" alt="Strapi supported version" />
</a>
</p>
<img style="width: 960px; height: auto;" src="public/screenshot.png" alt="Screenshot for Strapi preview button plugin" />
</div>

## Get Started

* [Features](#features)
* [Installation](#installation)
* [Compatability](#compatability)
* [Configuration](#configuration)
* [Plugin Options](#plugin-options)
* [Extending](#extending)
* [User Guide](#user-guide)
* [Troubleshooting](#troubleshooting)
* [Migration](#migration)
* [Support or Donate](#donate)
* [Roadmap](#roadmap)

## <a id="features"></a>✨ Features
* Adds a new button in content manager sidebar which links the user to a preview or live view of a frontend app.
Expand All @@ -35,6 +43,12 @@ yarn add strapi-plugin-preview-button@latest

Don't forget to **restart or rebuild** your Strapi app when installing a new plugin.

## <a id="compatability"></a>🔩 Compatibility
| Strapi version | Plugin version |
| - | - |
| v5 | v3 |
| v4 | v1, v2 |

## <a id="configuration"></a>🔧 Configuration
| property | type (default) | description |
| - | - | - |
Expand All @@ -59,11 +73,9 @@ Each object in the array requires the `uid` as well as `draft` and/or `published
#### Example
Consider we have a `Home` single type as well as `Page` and `Post` collection types, where each has a simple `title` and `content` field. The `Page` and `Post` models will also use a `uid` field named `slug` so they can create many entries with unique paths. Here is the minimum recommended config for this scenario.

```js
// ./config/plugins.js
'use strict';

module.exports = {
```ts
// ./config/plugins.ts`
export default () => ({
'preview-button': {
config: {
contentTypes: [
Expand Down Expand Up @@ -102,7 +114,7 @@ module.exports = {
],
},
},
};
});
```

In this example, the `Home` page is a single type and does not have `draftAndPublish` enabled so we do not use the `draft` prop.
Expand Down Expand Up @@ -131,8 +143,8 @@ For example, depending on how you are choosing to handle your preview method, yo

> **Unmatched values** will be replaced with an empty string.

```js
// ./config/plugins.js
```ts
// ./config/plugins.ts`
{
uid: 'api::page.page',
draft: {
Expand All @@ -151,8 +163,8 @@ For example, depending on how you are choosing to handle your preview method, yo
#### Use with localization enabled
If you have localization enabled for a content type, the `locale` value will be included in the entry data and replaced like the rest. You can simply use `{locale}` to include it where you like in the URL or query string.

```js
// ./config/plugins.js
```ts
// ./config/plugins.ts`
{
uid: 'api::page.page',
draft: {
Expand All @@ -172,11 +184,9 @@ If you have localization enabled for a content type, the `locale` value will be
#### Use a secret key with preview URLs
You can optionally use a secret key with your preview URLs by taking advantage of environment vars and the `query` prop. See example below.

```js
// ./config/plugins.js
'use strict';

module.exports = ({ env }) => ({
```ts
// ./config/plugins.ts`
export default ({ env }) => ({
'preview-button': {
config: {
contentTypes: [
Expand Down Expand Up @@ -219,8 +229,8 @@ By default this value is set to `StrapiPreview` but it can be any custom string.

If you would rather have the preview button always open in a new tab, you could use `_blank` as the value. Special target keywords such as `_blank`, `_top`, `_self`, or `_parent` are also acceptable values.

```js
// ./config/plugins.js
```ts
// ./config/plugins.ts`
{
uid: 'api::page.page',
draft: {
Expand All @@ -240,11 +250,9 @@ If you would rather have the preview button always open in a new tab, you could

You could also use a different `openTarget` for each model schema if you wanted to have each collection type open in it's own designated tab or window, like in the example below.

```js
// ./config/plugins.js
'use strict';

module.exports = {
```ts
// ./config/plugins.ts`
export default () => ({
'preview-button': {
config: {
contentTypes: [
Expand Down Expand Up @@ -281,14 +289,14 @@ module.exports = {
],
},
},
};
});
```

#### Disable copy link button
The "copy link" button located beneath the preview button can be disabled with the `copy: false` prop applied to `draft` and `published` configurations. This value is `true` by default.

```js
// ./config/plugins.js
```ts
// ./config/plugins.ts`
{
uid: 'api::home.home',
published: {
Expand All @@ -303,8 +311,8 @@ In **published mode**, the preview button changes to a "live view" button. If yo

In **draft mode**, the live view buttons will not appear.

```js
// ./config/plugins.js
```ts
// ./config/plugins.ts`
{
uid: 'api::page.page',
draft: {
Expand All @@ -331,8 +339,8 @@ In **draft mode**, the live view buttons will not appear.
### `listViewColumn`
Set to `false` to disable the preview and copy link buttons from displaying in list view.

```js
// ./src/api/page/content-types/page/schema.js
```ts
// ./src/api/page/content-types/page/schema.ts
{
"kind": "collectionType",
"collectionName": "pages",
Expand All @@ -356,75 +364,30 @@ Set to `false` to disable the preview and copy link buttons from displaying in l
}
```

Ideally, the preview and copy link buttons in list view should appear alongside the other action icons for each row in the table. However, Strapi does not currently provide a hook to append new icons to that column. For now, this plugin will add its own "Preview" column with the extra icon actions.

<img style="width: 960px; height: auto;" src="public/list-view.png" alt="Screenshot for list view in Strapi preview button plugin" />

## <a id="extending"></a>🔩 Extending
If you need to apply more advanced logic to the preview URL, you can accomplish this with the `plugin/preview-button/before-build-url` hook included with this plugin.

Your Strapi app will need a **custom plugin** in order to use this hook.

> See [Plugins Development](https://docs.strapi.io/developer-docs/latest/development/plugins-development.html) in Strapi docs for more info.
> See [Plugins Development](https://docs.strapi.io/dev-docs/plugins/developing-plugins) in Strapi docs for more info.

#### Example
In this example, we will create the bare minimum for a Strapi plugin that allows us to run our custom hook. The file structure for the plugin will look like the code below.
In the code below, we register the hook and the plugin in the `register` method of the plugin's `admin/src/index.ts` file.

```
/src/plugins/example
/admin
/src
index.js
package.json
strapi-admin.js
```
The callback receives `draft` and `published` parameters which are the same as the UID configs from `config/plugins.ts`. So if you are editing a `Page`, you will get the `draft` and `published` configs for `api::page.page` from your plugin config passed into the callback. The `data` and `uid` props are also provided to help mutate the `draft` and `published` configs.

The `package.json` is required for a Strapi plugin.
In this example, we are just adding on a `foo=bar` query parameter to demonstrate how this hook can be utilized for more dynamic URLs.

```js
// ./package.json
{
"name": "example",
"version": "0.1.0",
"description": "Example.",
"strapi": {
"displayName": "Example",
"name": "example",
"description": "Example",
"kind": "plugin"
},
"dependencies": {}
}
```

```js
// ./strapi-admin.js
'use strict';

module.exports = require('./admin/src').default;
```

In the main plugin file below, we register the plugin in the `register` method and we register the hook with the `bootstrap` method.

The hook provides `draft` and `published` parameters which are the same as the UID configs from `config/plugins.js`. So if you are editing a `Page`, you will get the `draft` and `published` configs for `api::page.page` from your plugin config passed into the callback.

Here you will modify and return `draft` and `published` while using `data` however you like. In this example, we are just adding on a `foo=bar` query parameter to demonstrate how this hook can be utilized for more dynamic URLs.

```js
// ./admin/src/index.js
```ts
// ./admin/src/index.ts
export default {
register(app) {
app.registerPlugin({
id: 'example',
name: 'example',
});
},

bootstrap(app) {
app.registerHook('plugin/preview-button/before-build-url', ({ data, draft, published }) => {
app.registerHook('plugin/preview-button/before-build-url', ({ data, draft, published, uid }) => {
const draftQuery = draft?.query ?? {};

// Return an object with modified `draft` and `published` props using `data` however you like.
// Return an object with modified `draft` and `published` props.
return {
draft: {
...draft,
Expand All @@ -436,22 +399,25 @@ export default {
published,
};
});

app.registerPlugin({
id: 'example',
name: 'Example',
});
},
};
```

Finally, don't forget to enable your plugin in your app by adding it to `config/plugins.js`.
Finally, don't forget to enable your plugin in your app by adding it to `config/plugins.ts`.

```js
// ./config/plugins.js
'use strict';

module.exports = {
```ts
// ./config/plugins.ts`
export default () => ({
example: {
enabled: true,
resolve: './src/plugins/example',
},
};
});
```

## <a id="user-guide"></a>📘 User Guide
Expand All @@ -463,7 +429,7 @@ The **Open draft preview** button should lead to an endpoint that redirects to t

For in-depth examples and instructions, please reference the links below to learn how this can be accomplished with Next.js and Strapi.

* [Next.js Preview Mode](https://nextjs.org/docs/advanced-features/preview-mode)
* [Next.js Preview Mode](https://nextjs.org/docs/pages/building-your-application/configuring/preview-mode)
* [Next.js Preview Mode example with Strapi](https://github.com/vercel/next.js/tree/canary/examples/cms-strapi)

## <a id="troubleshooting"></a>💩 Troubleshooting
Expand All @@ -482,7 +448,3 @@ Follow the [migration guides](MIGRATION.md) to keep your preview button plugin u

## <a id="donate"></a>❤️ Support or Donate
If you are enjoying this plugin and feel extra appreciative, you can [buy me a beer or 3 🍺🍺🍺](https://www.buymeacoffee.com/mattmilburn).

## <a id="roadmap"></a>🚧 Roadmap
* Custom validation hook.
* RBAC support.
9 changes: 7 additions & 2 deletions admin/src/components/CopyLinkButton/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { memo, useCallback } from 'react';
import { useIntl } from 'react-intl';
import { CopyToClipboard } from 'react-copy-to-clipboard';
import styled from 'styled-components';
import { Button } from '@strapi/design-system';
import { Link as LinkIcon } from '@strapi/icons';
import { useNotification } from '@strapi/strapi/admin';
Expand All @@ -12,6 +13,10 @@ export interface CopyLinkButtonProps {
url: string;
}

const ButtonStyled = styled(Button)`
width: 100%;
`;

const CopyLinkButton = ({ isDraft, url }: CopyLinkButtonProps) => {
const { formatMessage } = useIntl();
const { toggleNotification } = useNotification();
Expand All @@ -28,7 +33,7 @@ const CopyLinkButton = ({ isDraft, url }: CopyLinkButtonProps) => {

return (
<CopyToClipboard text={url} onCopy={handleOnCopy}>
<Button size="S" startIcon={<LinkIcon />} variant="secondary" style={{ width: '100%' }}>
<ButtonStyled size="S" startIcon={<LinkIcon />} variant="secondary">
{formatMessage(
isDraft
? {
Expand All @@ -40,7 +45,7 @@ const CopyLinkButton = ({ isDraft, url }: CopyLinkButtonProps) => {
defaultMessage: 'Copy link',
}
)}
</Button>
</ButtonStyled>
</CopyToClipboard>
);
};
Expand Down
Loading