diff --git a/packages/netlify-cms-backend-github/src/API.ts b/packages/netlify-cms-backend-github/src/API.ts
index 0a1a7da2e033..3cc6f7b7854b 100644
--- a/packages/netlify-cms-backend-github/src/API.ts
+++ b/packages/netlify-cms-backend-github/src/API.ts
@@ -818,15 +818,6 @@ export default class API {
return cmsBranches;
}
- async latestRelease() {
- console.log(
- '%c Loading latest release',
- 'line-height: 30px;text-align: center;font-weight: bold',
- );
-
- return this.request(`${this.repoURL}/releases/latest`)
- }
-
async listReleases() {
console.log(
'%c Loading releases',
diff --git a/packages/netlify-cms-core/src/components/Releases/WorkflowCard.js b/packages/netlify-cms-core/src/components/Releases/WorkflowCard.js
deleted file mode 100644
index 0ca914afe88d..000000000000
--- a/packages/netlify-cms-core/src/components/Releases/WorkflowCard.js
+++ /dev/null
@@ -1,177 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { css } from '@emotion/core';
-import styled from '@emotion/styled';
-import { translate } from 'react-polyglot';
-import { Link } from 'react-router-dom';
-import { components, colors, colorsRaw, transitions, buttons } from 'netlify-cms-ui-default';
-
-const styles = {
- text: css`
- font-size: 13px;
- font-weight: normal;
- margin-top: 4px;
- `,
- button: css`
- ${buttons.button};
- width: auto;
- flex: 1 0 0;
- font-size: 13px;
- padding: 6px 0;
- `,
-};
-
-const WorkflowLink = styled(Link)`
- display: block;
- padding: 0 18px 18px;
- height: 200px;
- overflow: hidden;
-`;
-
-const CardCollection = styled.div`
- font-size: 14px;
- color: ${colors.textLead};
- text-transform: uppercase;
- margin-top: 12px;
- text-overflow: ellipsis;
- overflow: hidden;
- white-space: nowrap;
-`;
-
-const CardTitle = styled.h2`
- margin: 28px 0 0;
- color: ${colors.textLead};
-`;
-
-const CardDateContainer = styled.div`
- ${styles.text};
-`;
-
-const CardBody = styled.p`
- ${styles.text};
- color: ${colors.text};
- margin: 24px 0 0;
- overflow-wrap: break-word;
- word-break: break-word;
- hyphens: auto;
-`;
-
-const CardButtonContainer = styled.div`
- background-color: ${colors.foreground};
- position: absolute;
- bottom: 0;
- width: 100%;
- padding: 12px 18px;
- display: flex;
- opacity: 0;
- transition: opacity ${transitions.main};
- cursor: pointer;
-`;
-
-const DeleteButton = styled.button`
- ${styles.button};
- background-color: ${colorsRaw.redLight};
- color: ${colorsRaw.red};
- margin-right: 6px;
-`;
-
-const PublishButton = styled.button`
- ${styles.button};
- background-color: ${colorsRaw.teal};
- color: ${colors.textLight};
- margin-left: 6px;
-
- &[disabled] {
- ${buttons.disabled};
- }
-`;
-
-const WorkflowCardContainer = styled.div`
- ${components.card};
- margin-bottom: 24px;
- position: relative;
- overflow: hidden;
-
- &:hover ${CardButtonContainer} {
- opacity: 1;
- }
-`;
-
-function lastChangePhraseKey(date, author) {
- if (date && author) {
- return 'lastChange';
- } else if (date) {
- return 'lastChangeNoAuthor';
- } else if (author) {
- return 'lastChangeNoDate';
- }
-}
-
-const CardDate = translate()(({ t, date, author }) => {
- const key = lastChangePhraseKey(date, author);
- if (key) {
- return (
- {t(`workflow.workflowCard.${key}`, { date, author })}
- );
- }
-});
-
-function WorkflowCard({
- collectionLabel,
- title,
- authorLastChange,
- body,
- isModification,
- editLink,
- timestamp,
- onDelete,
- allowPublish,
- canPublish,
- onPublish,
- postAuthor,
- t,
-}) {
- return (
-
-
- {collectionLabel}
- {postAuthor}
- {title}
- {(timestamp || authorLastChange) && }
- {body}
-
-
-
- {isModification
- ? t('workflow.workflowCard.deleteChanges')
- : t('workflow.workflowCard.deleteNewEntry')}
-
- {allowPublish && (
-
- {isModification
- ? t('workflow.workflowCard.publishChanges')
- : t('workflow.workflowCard.publishNewEntry')}
-
- )}
-
-
- );
-}
-
-WorkflowCard.propTypes = {
- collectionLabel: PropTypes.string.isRequired,
- title: PropTypes.string,
- authorLastChange: PropTypes.string,
- body: PropTypes.string,
- isModification: PropTypes.bool,
- editLink: PropTypes.string.isRequired,
- timestamp: PropTypes.string.isRequired,
- onDelete: PropTypes.func.isRequired,
- allowPublish: PropTypes.bool.isRequired,
- canPublish: PropTypes.bool.isRequired,
- onPublish: PropTypes.func.isRequired,
- postAuthor: PropTypes.string,
- t: PropTypes.func.isRequired,
-};
-
-export default translate()(WorkflowCard);
diff --git a/packages/netlify-cms-core/src/components/Releases/WorkflowList.js b/packages/netlify-cms-core/src/components/Releases/WorkflowList.js
deleted file mode 100644
index 7e0a9a7ba608..000000000000
--- a/packages/netlify-cms-core/src/components/Releases/WorkflowList.js
+++ /dev/null
@@ -1,269 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import ImmutablePropTypes from 'react-immutable-proptypes';
-import { css } from '@emotion/core';
-import styled from '@emotion/styled';
-import moment from 'moment';
-import { translate } from 'react-polyglot';
-import { colors, lengths } from 'netlify-cms-ui-default';
-
-import { status } from '../../constants/publishModes';
-import { DragSource, DropTarget, HTML5DragDrop } from '../UI';
-import WorkflowCard from './WorkflowCard';
-import { selectEntryCollectionTitle } from '../../reducers/collections';
-
-const WorkflowListContainer = styled.div`
- min-height: 60%;
- display: grid;
- grid-template-columns: 33.3% 33.3% 33.3%;
-`;
-
-const WorkflowListContainerOpenAuthoring = styled.div`
- min-height: 60%;
- display: grid;
- grid-template-columns: 50% 50% 0%;
-`;
-
-const styles = {
- columnPosition: idx =>
- (idx === 0 &&
- css`
- margin-left: 0;
- `) ||
- (idx === 2 &&
- css`
- margin-right: 0;
- `) ||
- css`
- &:before,
- &:after {
- content: '';
- display: block;
- position: absolute;
- width: 2px;
- height: 80%;
- top: 76px;
- background-color: ${colors.textFieldBorder};
- }
-
- &:before {
- left: -23px;
- }
-
- &:after {
- right: -23px;
- }
- `,
- column: css`
- margin: 0 20px;
- transition: background-color 0.5s ease;
- border: 2px dashed transparent;
- border-radius: 4px;
- position: relative;
- height: 100%;
- `,
- columnHovered: css`
- border-color: ${colors.active};
- `,
- hiddenColumn: css`
- display: none;
- `,
- hiddenRightBorder: css`
- &:not(:first-child):not(:last-child) {
- &:after {
- display: none;
- }
- }
- `,
-};
-
-const ColumnHeader = styled.h2`
- font-size: 20px;
- font-weight: normal;
- padding: 4px 14px;
- border-radius: ${lengths.borderRadius};
- margin-bottom: 28px;
-
- ${props =>
- props.name === 'draft' &&
- css`
- background-color: ${colors.statusDraftBackground};
- color: ${colors.statusDraftText};
- `}
-
- ${props =>
- props.name === 'pending_review' &&
- css`
- background-color: ${colors.statusReviewBackground};
- color: ${colors.statusReviewText};
- `}
-
- ${props =>
- props.name === 'pending_publish' &&
- css`
- background-color: ${colors.statusReadyBackground};
- color: ${colors.statusReadyText};
- `}
-`;
-
-const ColumnCount = styled.p`
- font-size: 13px;
- font-weight: 500;
- color: ${colors.text};
- text-transform: uppercase;
- margin-bottom: 6px;
-`;
-
-// This is a namespace so that we can only drop these elements on a DropTarget with the same
-const DNDNamespace = 'cms-workflow';
-
-function getColumnHeaderText(columnName, t) {
- switch (columnName) {
- case 'draft':
- return t('workflow.workflowList.draftHeader');
- case 'pending_review':
- return t('workflow.workflowList.inReviewHeader');
- case 'pending_publish':
- return t('workflow.workflowList.readyHeader');
- }
-}
-
-class WorkflowList extends React.Component {
- static propTypes = {
- entries: ImmutablePropTypes.orderedMap,
- handleChangeStatus: PropTypes.func.isRequired,
- handlePublish: PropTypes.func.isRequired,
- handleDelete: PropTypes.func.isRequired,
- t: PropTypes.func.isRequired,
- isOpenAuthoring: PropTypes.bool,
- collections: ImmutablePropTypes.map.isRequired,
- };
-
- handleChangeStatus = (newStatus, dragProps) => {
- const slug = dragProps.slug;
- const collection = dragProps.collection;
- const oldStatus = dragProps.ownStatus;
- this.props.handleChangeStatus(collection, slug, oldStatus, newStatus);
- };
-
- requestDelete = (collection, slug, ownStatus) => {
- if (window.confirm(this.props.t('workflow.workflowList.onDeleteEntry'))) {
- this.props.handleDelete(collection, slug, ownStatus);
- }
- };
-
- requestPublish = (collection, slug, ownStatus) => {
- if (ownStatus !== status.last()) {
- window.alert(this.props.t('workflow.workflowList.onPublishingNotReadyEntry'));
- return;
- } else if (!window.confirm(this.props.t('workflow.workflowList.onPublishEntry'))) {
- return;
- }
- this.props.handlePublish(collection, slug);
- };
-
- // eslint-disable-next-line react/display-name
- renderColumns = (entries, column) => {
- const { isOpenAuthoring, collections, t } = this.props;
- if (!entries) return null;
-
- if (!column) {
- return entries.entrySeq().map(([currColumn, currEntries], idx) => (
-
- {(connect, { isHovered }) =>
- connect(
-
-
-
- {getColumnHeaderText(currColumn, this.props.t)}
-
-
- {this.props.t('workflow.workflowList.currentEntries', {
- smart_count: currEntries.size,
- })}
-
- {this.renderColumns(currEntries, currColumn)}
-
-
,
- )
- }
-
- ));
- }
- return (
-
- {entries.map(entry => {
- const timestamp = moment(entry.get('updatedOn')).format(
- t('workflow.workflow.dateFormat'),
- );
- const slug = entry.get('slug');
- const collectionName = entry.get('collection');
- const editLink = `collections/${collectionName}/entries/${slug}?ref=workflow`;
- const ownStatus = entry.get('status');
- const collection = collections.find(
- collection => collection.get('name') === collectionName,
- );
- const collectionLabel = collection?.get('label');
- const isModification = entry.get('isModification');
-
- const allowPublish = collection?.get('publish');
- const canPublish = ownStatus === status.last() && !entry.get('isPersisting', false);
- const postAuthor = entry.get('author');
-
- return (
-
- {connect =>
- connect(
-
-
-
,
- )
- }
-
- );
- })}
-
- );
- };
-
- render() {
- const columns = this.renderColumns(this.props.entries);
- const ListContainer = this.props.isOpenAuthoring
- ? WorkflowListContainerOpenAuthoring
- : WorkflowListContainer;
- return {columns};
- }
-}
-
-export default HTML5DragDrop(translate()(WorkflowList));
diff --git a/packages/netlify-cms-lib-util/src/implementation.ts b/packages/netlify-cms-lib-util/src/implementation.ts
index 2c25f2a7c7ca..a3af012fb1e4 100644
--- a/packages/netlify-cms-lib-util/src/implementation.ts
+++ b/packages/netlify-cms-lib-util/src/implementation.ts
@@ -143,9 +143,9 @@ export interface Implementation {
persistMedia: (file: AssetProxy, opts: PersistOptions) => Promise;
deleteFiles: (paths: string[], commitMessage: string) => Promise;
- latestRelease: () => Promise<{}>;
listReleases: () => Promise;
publishRelease: (version: string) => Promise;
+
unpublishedEntries: () => Promise;
unpublishedEntry: (args: {
id?: string;
@@ -263,17 +263,6 @@ export async function entriesByFiles(
return fetchFiles(files, readFile, readFileMetadata, apiName);
}
-export async function latestRelease(latestRelease: () => Promise<{}>) {
- try {
- return await latestRelease();
- } catch (error) {
- if (error.message === 'Not Found') {
- return Promise.resolve({});
- }
- throw error;
- }
-}
-
export async function listReleases(listReleases: () => Promise) {
try {
const keys = await listReleases();