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

Pulls/4.11/dual api #4

Draft
wants to merge 16 commits into
base: 4.11
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
4,921 changes: 4,920 additions & 1 deletion client/dist/js/bundle.js

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion client/dist/styles/bundle.css

Large diffs are not rendered by default.

89 changes: 56 additions & 33 deletions client/src/boot/registerTransforms.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@ import Injector from 'lib/Injector';
import readOneBlockQuery from 'state/history/readOneBlockQuery';
import HistoricElementViewFactory from 'components/HistoricElementView/HistoricElementView';
import revertToBlockVersionMutation from 'state/history/revertToBlockVersionMutation';
import revertToBlockVersionRequest from 'state/history/revertToBlockVersionRequest';
import readBlocksForAreaQuery from 'state/editor/readBlocksForAreaQuery';
import addElementToArea from 'state/editor/addElementMutation';
import ArchiveAction from 'components/ElementActions/ArchiveAction';
import DuplicateAction from 'components/ElementActions/DuplicateAction';
import PublishAction from 'components/ElementActions/PublishAction';
import SaveAction from 'components/ElementActions/SaveAction';
import UnpublishAction from 'components/ElementActions/UnpublishAction';
import { getConfig} from 'state/editor/elementConfig';

export default () => {

Injector.transform(
'elemental-fieldgroup',
(updater) => {
Expand All @@ -37,41 +40,61 @@ export default () => {
}
);

Injector.transform(
'blocks-history-revert',
(updater) => {
// Add block element revert GraphQL mutation to the HistoryViewerToolbar
updater.component(
'HistoryViewerToolbar.VersionedAdmin.HistoryViewer.Element.HistoryViewerVersionDetail',
revertToBlockVersionMutation,
'BlockRevertMutation'
);
}
);
// REST
if (!getConfig().useGraphql) {
Injector.transform(
'blocks-history-revert',
(updater) => {
// Add revertToVersion() to props.actions on HistoryViewerToolbar
updater.component(
'HistoryViewerToolbar.VersionedAdmin.HistoryViewer.Element.HistoryViewerVersionDetail',
revertToBlockVersionRequest,
'BlockRevertRequest'
);
}
);
}

Injector.transform(
'cms-element-editor',
(updater) => {
// Add GraphQL query for reading elements on a page for the ElementEditor
updater.component(
'ElementList',
readBlocksForAreaQuery,
'PageElements'
);
}
);
// GRAPHQL
if (getConfig().useGraphql) {
Injector.transform(
'blocks-history-revert',
(updater) => {
// Add block element revert GraphQL mutation to the HistoryViewerToolbar
// This is the yellow revert button at the bottom on
// /admin/pages/edit/EditForm/6/field/ElementalArea/item/2/edit#Root_History
updater.component(
'HistoryViewerToolbar.VersionedAdmin.HistoryViewer.Element.HistoryViewerVersionDetail',
revertToBlockVersionMutation,
'BlockRevertMutation'
);
}
);

Injector.transform(
'cms-element-adder',
(updater) => {
// Add GraphQL query for adding elements to an ElementEditor (ElementalArea)
updater.component(
'AddElementPopover',
addElementToArea,
'ElementAddButton'
);
}
);
Injector.transform(
'cms-element-editor',
(updater) => {
// Add GraphQL query for reading elements on a page for the ElementEditor
updater.component(
'ElementList',
readBlocksForAreaQuery,
'PageElements'
);
}
);

Injector.transform(
'cms-element-adder',
(updater) => {
// Add GraphQL query for adding elements to an ElementEditor (ElementalArea)
updater.component(
'AddElementPopover',
addElementToArea,
'ElementAddButton'
);
}
);
}

// Add elemental editor actions
Injector.transform('element-actions', (updater) => {
Expand Down
38 changes: 26 additions & 12 deletions client/src/components/ElementActions/ArchiveAction.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,51 @@
/* global window */
import React from 'react';
import React, { useContext } from 'react';
import { compose } from 'redux';
import AbstractAction from 'components/ElementActions/AbstractAction';
import archiveBlockMutation from 'state/editor/archiveBlockMutation';
import i18n from 'i18n';
import { ElementEditorContext } from 'components/ElementEditor/ElementEditor';
import backend from 'lib/Backend';
import { getConfig } from 'state/editor/elementConfig';

/**
* Adds the elemental menu action to archive a block of any state
*/
const ArchiveAction = (MenuComponent) => (props) => {
const { fetchBlocks } = useContext(ElementEditorContext);

const handleClick = (event) => {
event.stopPropagation();

const { element: { id }, isPublished, actions: { handleArchiveBlock } } = props;

const isPublished = props.element.isPublished;
let archiveMessage = i18n._t(
'ElementArchiveAction.CONFIRM_DELETE',
'Are you sure you want to send this block to the archive?'
);

if (isPublished) {
archiveMessage = i18n._t(
'ElementArchiveAction.CONFIRM_DELETE_AND_UNPUBLISH',
'Warning: This block will be unpublished before being sent to the archive. Are you sure you want to proceed?'
);
}

// eslint-disable-next-line no-alert
if (handleArchiveBlock && window.confirm(archiveMessage)) {
handleArchiveBlock(id).then(() => {
const preview = window.jQuery('.cms-preview');
preview.entwine('ss.preview')._loadUrl(preview.find('iframe').attr('src'));
});
if (!window.confirm(archiveMessage)) {
return;
}
if (getConfig().useGraphql) {
const { element: { id }, actions: { handleArchiveBlock } } = props;
// eslint-disable-next-line no-alert
if (handleArchiveBlock) {
handleArchiveBlock(id).then(() => {
const preview = window.jQuery('.cms-preview');
preview.entwine('ss.preview')._loadUrl(preview.find('iframe').attr('src'));
});
}
} else {
const id = props.element.id;
const url = `${getConfig().controllerLink.replace(/\/$/, '')}/archive`;
backend.post(url, {
ID: id,
})
.then(() => fetchBlocks());
}
};

Expand Down
32 changes: 22 additions & 10 deletions client/src/components/ElementActions/DuplicateAction.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
/* global window */
import React from 'react';
import React, { useContext } from 'react';
import { compose } from 'redux';
import AbstractAction from 'components/ElementActions/AbstractAction';
import duplicateBlockMutation from 'state/editor/duplicateBlockMutation';
import i18n from 'i18n';
import { ElementEditorContext } from 'components/ElementEditor/ElementEditor';
import backend from 'lib/Backend';
import { getConfig } from 'state/editor/elementConfig';

/**
* Adds the elemental menu action to duplicate a block
*/
const DuplicateAction = (MenuComponent) => (props) => {
const { fetchBlocks } = useContext(ElementEditorContext);

if (props.type.broken) {
// Don't allow this action for a broken element.
return (
Expand All @@ -18,16 +23,23 @@ const DuplicateAction = (MenuComponent) => (props) => {

const handleClick = (event) => {
event.stopPropagation();

const { element: { id }, actions: { handleDuplicateBlock } } = props;

if (handleDuplicateBlock) {
handleDuplicateBlock(id).then(() => {
const preview = window.jQuery('.cms-preview');
preview.entwine('ss.preview')._loadUrl(preview.find('iframe').attr('src'));
});
if (getConfig().useGraphql) {
const { element: { id }, actions: { handleDuplicateBlock } } = props;
if (handleDuplicateBlock) {
handleDuplicateBlock(id).then(() => {
const preview = window.jQuery('.cms-preview');
preview.entwine('ss.preview')._loadUrl(preview.find('iframe').attr('src'));
});
}
} else {
const id = props.element.id;
const url = `${getConfig().controllerLink.replace(/\/$/, '')}/duplicate`;
backend.post(url, {
ID: id,
})
.then(() => fetchBlocks());
}
};
}

const disabled = props.element.canCreate !== undefined && !props.element.canCreate;
const label = i18n._t('ElementArchiveAction.DUPLICATE', 'Duplicate');
Expand Down
23 changes: 20 additions & 3 deletions client/src/components/ElementActions/PublishAction.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* global window */
import React from 'react';
import React, { useContext } from 'react';
import { compose } from 'redux';
import AbstractAction from 'components/ElementActions/AbstractAction';
import publishBlockMutation from 'state/editor/publishBlockMutation';
Expand All @@ -9,6 +9,8 @@ import { connect } from 'react-redux';
import { loadElementSchemaValue } from 'state/editor/loadElementSchemaValue';
import { loadElementFormStateName } from 'state/editor/loadElementFormStateName';
import { initialize } from 'redux-form';
import { ElementEditorContext } from 'components/ElementEditor/ElementEditor';
import { getConfig } from 'state/editor/elementConfig';

/**
* Show a toast message reporting whether publication of Element was successful
Expand Down Expand Up @@ -76,6 +78,8 @@ const performSaveForElementWithFormData = (id, formData, securityId) => {
* Adds the elemental menu action to publish a draft/modified block
*/
const PublishAction = (MenuComponent) => (props) => {
const { fetchBlocks } = useContext(ElementEditorContext);

if (props.type.broken) {
// Don't allow this action for a broken element.
return (
Expand All @@ -85,6 +89,20 @@ const PublishAction = (MenuComponent) => (props) => {

const { element, formDirty } = props;

const publishElement = () => {
if (getConfig().useGraphql) {
const { element: { id }, actions: { handlePublishBlock } } = props;
return handlePublishBlock(id);
} else {
const id = props.element.id;
const url = `${getConfig().controllerLink.replace(/\/$/, '')}/publish`;
return backend.post(url, {
ID: id,
})
.then(() => fetchBlocks());
}
}

const handleClick = (event) => {
event.stopPropagation();

Expand All @@ -96,7 +114,6 @@ const PublishAction = (MenuComponent) => (props) => {
type,
securityId,
formData,
actions: { handlePublishBlock },
reinitialiseForm,
} = props;

Expand All @@ -113,7 +130,7 @@ const PublishAction = (MenuComponent) => (props) => {

// Perform publish. Data is assumed to be up to date
actionFlow
.then(() => handlePublishBlock(id))
.then(() => publishElement())
.then(() => reportPublicationStatus(type.title, title, true))
.catch(() => reportPublicationStatus(type.title, title, false));
};
Expand Down
26 changes: 15 additions & 11 deletions client/src/components/ElementActions/SaveAction.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* global window */
import React from 'react';
import React, { useContext } from 'react';
import { compose } from 'redux';
import { connect } from 'react-redux';
import AbstractAction from 'components/ElementActions/AbstractAction';
Expand All @@ -8,12 +8,16 @@ import i18n from 'i18n';
import { loadElementSchemaValue } from 'state/editor/loadElementSchemaValue';
import { loadElementFormStateName } from 'state/editor/loadElementFormStateName';
import { initialize } from 'redux-form';
import { ElementEditorContext } from 'components/ElementEditor/ElementEditor';
import { getConfig } from 'state/editor/elementConfig';

/**
* Using a REST backend, serialize the current form data and post it to the backend endpoint to save
* the inline edit form's data for the current block.
*/
const SaveAction = (MenuComponent) => (props) => {
const { fetchBlocks } = useContext(ElementEditorContext);

if (!props.expandable || props.type.broken) {
// Some elemental blocks can not be edited inline (e.g. User form blocks)
// We don't want to add a "Save" action for those blocks.
Expand Down Expand Up @@ -47,16 +51,16 @@ const SaveAction = (MenuComponent) => (props) => {
const endpoint = backend.createEndpointFetcher(endpointSpec);
endpoint(formData)
.then(() => {
// Update the Apollo query cache with the new form data
const { apolloClient } = window.ss;

// @todo optimistically update the data for the current element instead of
// rerunning the whole query
apolloClient.queryManager.reFetchObservableQueries();
reinitialiseForm(formData);

const preview = $('.cms-preview');
preview.entwine('ss.preview')._loadUrl(preview.find('iframe').attr('src'));
if (getConfig().useGraphql) {
// Update the Apollo query cache with the new form data
const { apolloClient } = window.ss;
// @todo optimistically update the data for the current element instead of
// rerunning the whole query
apolloClient.queryManager.reFetchObservableQueries();
reinitialiseForm(formData);
}

fetchBlocks();

const newTitle = formData ? formData[`PageElements_${element.id}_Title`] : null;
$.noticeAdd({
Expand Down
Loading
Loading