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();