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

feat: wait for onsyschange #9

Merged
merged 15 commits into from
Oct 6, 2021
Merged
110 changes: 59 additions & 51 deletions apps/gatsby/src/Sidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,11 @@ import React from 'react';
import PropTypes from 'prop-types';
import { ExtensionUI } from '@gatsby-cloud-pkg/gatsby-cms-extension-base';

import {
Spinner,
HelpText,
Icon,
} from '@contentful/forma-36-react-components';
import { Spinner, HelpText, Icon } from '@contentful/forma-36-react-components';

const STATUS_STYLE = { textAlign: 'center', color: '#7f7c82' };
const ICON_STYLE = { marginBottom: '-4px' };
const GATSBY_PREVIEW_TAB_ID = `GATSBY_TAB`

const callWebhook = (webhookUrl, authToken) => fetch(webhookUrl, {
method: 'POST',
Expand All @@ -33,6 +30,7 @@ export default class Sidebar extends React.Component {
slug: null,
manifestId: null,
lastPublishedDateTime: null,
buttonDisabled: false,
};

this.sdk = props.sdk;
Expand All @@ -43,6 +41,7 @@ export default class Sidebar extends React.Component {
this.sdk.window.startAutoResizer();

const content = this.props.sdk.entry.getSys();

this.setManifestId(content);
this.setLastPublishedDateTime(content);
}
Expand Down Expand Up @@ -164,48 +163,18 @@ export default class Sidebar extends React.Component {
this.setState({ slug: finalSlug })
}

manuallySaveContentEntry = async () => {
const { entry, space, ids } = this.props.sdk;
const fields = Object.entries(entry.fields);

const updatedEntry = await space.getEntry(ids.entry);

fields.forEach(([fieldName, field]) => {
const { locales } = field;

locales.forEach((locale) => {
const fieldLocale = field._getFieldLocale(locale);
const fieldValue = fieldLocale.getValue();

// if a field was previously empty, it will not be on the updateEntry object
let updateField = updatedEntry.fields[fieldName];
if (!updateField) {
updateField = {};
updatedEntry.fields[fieldName] = updateField;
}

updateField[locale] = fieldValue;
});
});

return space.updateEntry(updatedEntry);
}

refreshPreview = async () => {
refreshPreview = () => {
const {
webhookUrl,
previewWebhookUrl,
authToken
} = this.sdk.parameters.installation;

await this.manuallySaveContentEntry();

if (previewWebhookUrl) {
callWebhook(previewWebhookUrl, authToken);
} else if (webhookUrl) {
callWebhook(webhookUrl, authToken);
} else {
// @todo show this in the UI
console.warn(`Please add a Preview Webhook URL to your Gatsby Cloud App settings.`)
}
};
Expand All @@ -224,6 +193,48 @@ export default class Sidebar extends React.Component {
return previewUrl;
}

handleContentSync = async () => {
if (this.state.buttonDisabled) {
return
}

this.setState({ buttonDisabled: true })

// Contentful takes a few seconds to save. If we do not wait a bit for this, then the Gatsby preview may be started and finish before any content is even saved on the Contentful side
await new Promise(resolve => setTimeout(resolve, 3000))

this.refreshPreview();

let previewUrl = this.getPreviewUrl()
console.info(`opening preview url ${previewUrl}`)
window.open(previewUrl, GATSBY_PREVIEW_TAB_ID)

// Wait to see if Contentful saves new data async
const interval = setInterval(() => {
const newPreviewUrl = this.getPreviewUrl()

if (previewUrl !== newPreviewUrl) {
clearInterval(interval)

previewUrl = newPreviewUrl

console.info(`new preview url ${newPreviewUrl}`)
window.open(previewUrl, GATSBY_PREVIEW_TAB_ID)

this.refreshPreview();
this.setState({ buttonDisabled: false })
}
}, 1000)

// after 10 seconds stop waiting for Contentful to save data
setTimeout(() => {
clearInterval(interval)
this.setState({ buttonDisabled: false })
}, 10000)
}



render = () => {
let {
contentSyncUrl,
Expand All @@ -240,21 +251,18 @@ export default class Sidebar extends React.Component {
<div className="extension">
<div className="flexcontainer">
{(previewWebhookUrl || webhookUrl) ?
<ExtensionUI
contentSlug={!contentSyncUrl && !!slug && slug}
previewUrl={previewUrl}
authToken={authToken}
onOpenPreviewButtonClick={async ({ previewWindow }) => {
await this.refreshPreview();
/**
* ExtensionUI returns a reference to the opened tab (previewWindow) after eagerly
* opening it with the given previewUrl. Because there is a small chance that this will
* have a stale manifestId, we update the url in the opened preview tab just in case
* to ensure that the user is redirected to the correct preview build
*/
previewWindow.location.href = this.getPreviewUrl();
}}
/> :
<>
<ExtensionUI
disabled={this.state.buttonDisabled}
disablePreviewOpen={!!contentSyncUrl}
contentSlug={!!slug && slug}
previewUrl={previewUrl}
authToken={authToken}
onOpenPreviewButtonClick={!!contentSyncUrl && this.handleContentSync}
/>
{!!this.state.buttonDisabled && <Spinner />}
</>
:
<HelpText style={STATUS_STYLE}>
<Icon icon="Warning" color="negative" style={ICON_STYLE} />
{' '}Please add a Preview Webhook URL to your Gatsby App settings.
Expand Down