Hi community,
apart from 'Save' I need another button in the right-side navigation which allows me to execute a server side script.
It would be great to use the same style as the default save button.
If it's not possible to add it at this place it could be any other easily accessible place.
As I'm not familiar with React adding a custom component with a new functionality is quite difficult for me.
Any help is appreciated.
Hey there,
So we have an implementation of preview buttons for our collections. I'm not really sure, but I think that you can use the Payload API in the React component and call a custom endpoint (https://payloadcms.com/docs/rest-api/overview#custom-endpoints)
Field config
import { Field } from "payload/types";
import { PreviewButtonField } from "./components/PreviewButtonField";
export const PreviewButtons: Field = {
name: "previewButtons",
label: "Voorbeeld",
type: "ui",
admin: {
position: "sidebar",
components: {
Field: PreviewButtonField,
}
}
}
React component:
import { Button } from "payload/components";
import { Label, useFormFields } from "payload/components/forms";
import React from "react";
import "./index.scss";
type Props = {
label?: string;
};
export const PreviewButtonField: React.FC = ({ label }: Props) => {
const url = useFormFields(([fields]) => fields.url);
return (
<>
<Label label={label} />
<div className="preview-buttons">
<a href={`${process.env.PAYLOAD_PUBLIC_FRONDEND_SERVER_URL ?? ''}${url.value}`} target="live-preview">
<Button
className="preview-button"
buttonStyle="primary"
>
Live
</Button>
</a>
<a href={`${process.env.PAYLOAD_PUBLIC_FRONDEND_SERVER_URL ?? ''}${url.value}?draft=true`} target="draft-preview">
<Button
className="preview-button"
buttonStyle="secondary"
>
Concept
</Button>
</a>
</div>
</>
);
};
And the styling:
.preview-buttons {
display: flex;
gap: 10px;
margin-bottom: 10px;
a,
button {
width: 100%;
margin: 0;
}
}
Hi Matthijs, that's a great starting point! I appreciate that a lot!
In order to contribute at least something, here's my implementation of a custom "publish" button component:
// deploy-button/index.js
export const deployButton = () => {
let siteID
useFormFields(([fields]) => {
siteID = fields.site.value
});
return (
<>
<div className="deploy-button-wrapper">
<a href={`/deploy-site?site=${siteID}`} target="_blank">
<button
className="deploy-button"
buttonStyle="secondary">Publish
</button>
</a>
<div className="field-description">Alle Änderungen hochladen. Das kann etwas
dauern.</div>
<ul className="field-description">
<li>Erst speichern</li>
<li>Erst am Ende der Sitzung ausführen</li>
</ul>
</div>
</>
);
};
Here the custom component is imported into a ui field:
// deployButtonField.js
import { deployButton } from '../components/deploy-button'
export const deployButtonField = {
type: 'ui',
name: 'deployButton',
label: {
de: 'Veröffentlichen',
en: 'Publish'
},
admin: {
position: "sidebar",
components: {
Field: deployButton,
}
}
}
Here, in server.js a custom route is used to trigger upload to hoster:
// server.js
/* route: deploy-site */
const routerDeploy = express.Router()
routerDeploy.use(payload.authenticate)
routerDeploy.use(async (req, res, next) => {
try {
if (req.user) {
const siteID = req.query.site
const site = await req.payload.findByID({ collection: 'sites', id: siteID, depth: 0 })
const cmd = `/home/payload/cms/scripts/un-deploy-site.sh ${site.domainShort}`
res.redirect(`https://${site.domain}`)
exec(cmd, (error, stdout, stderr) => {
if (error) {
log(`exec error: ${error}`, req.user.shortName, __filename)
return
}
if (stderr) {
log(`exec stderr: ${stderr}`, req.user.shortName, __filename)
}
log(`exec stdout: ${stdout}`, req.user.shortName, __filename)
})
}
else {
next()
}
} catch (error) {
log(error, '', __filename, 3)
mailError(error)
}
})
app.use('/deploy-site', routerDeploy)
Star
Discord
online
Get dedicated engineering support directly from the Payload team.