Skip to content
Open
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ coverage/
.temp/
storybook-static/
.nx
.claude/settings.local.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ function Entries({
getWorkflowStatus,
getUnpublishedEntries,
filterTerm,
sortFields,
}) {
const loadingMessages = [
t('collection.entries.loadingEntries'),
Expand All @@ -54,6 +55,7 @@ function Entries({
getWorkflowStatus={getWorkflowStatus}
getUnpublishedEntries={getUnpublishedEntries}
filterTerm={filterTerm}
sortFields={sortFields}
/>
{isFetching && page !== undefined && entries.size > 0 ? (
<PaginationMessage>{t('collection.entries.loadingEntries')}</PaginationMessage>
Expand All @@ -77,6 +79,7 @@ Entries.propTypes = {
getWorkflowStatus: PropTypes.func,
getUnpublishedEntries: PropTypes.func,
filterTerm: PropTypes.string,
sortFields: ImmutablePropTypes.list,
};

export default translate()(Entries);
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
selectEntriesLoaded,
selectIsFetching,
selectGroups,
selectEntriesSortFields,
} from '../../../reducers/entries';
import { selectUnpublishedEntry, selectUnpublishedEntriesByStatus } from '../../../reducers';
import { selectCollectionEntriesCursor } from '../../../reducers/cursors';
Expand Down Expand Up @@ -144,6 +145,7 @@ export class EntriesCollection extends React.Component {
getWorkflowStatus,
getUnpublishedEntries,
filterTerm,
sortFields,
} = this.props;

const EntriesToRender = ({ entries }) => {
Expand All @@ -160,6 +162,7 @@ export class EntriesCollection extends React.Component {
getWorkflowStatus={getWorkflowStatus}
getUnpublishedEntries={getUnpublishedEntries}
filterTerm={filterTerm}
sortFields={sortFields}
/>
);
};
Expand Down Expand Up @@ -206,6 +209,7 @@ function mapStateToProps(state, ownProps) {

let entries = selectEntries(state.entries, collection);
const groups = selectGroups(state.entries, collection);
const sortFields = selectEntriesSortFields(state.entries, collection.get('name'));

if (collection.has('nested')) {
const collectionFolder = collection.get('folder');
Expand Down Expand Up @@ -233,6 +237,7 @@ function mapStateToProps(state, ownProps) {
page,
entries,
groups,
sortFields,
entriesLoaded,
isFetching,
viewStyle,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,18 @@ import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import styled from '@emotion/styled';
import { Waypoint } from 'react-waypoint';
import { Map, List } from 'immutable';

import { selectFields, selectInferredField } from '../../../reducers/collections';
import { Map, List, fromJS } from 'immutable';
import { translate } from 'react-polyglot';
import orderBy from 'lodash/orderBy';
import { colors } from 'decap-cms-ui-default';

import {
selectFields,
selectInferredField,
selectSortDataPath,
} from '../../../reducers/collections';
import { filterNestedEntries } from './EntriesCollection';
import { SortDirection } from '../../../types/redux';
import EntryCard from './EntryCard';

const CardsGrid = styled.ul`
Expand All @@ -18,6 +26,20 @@ const CardsGrid = styled.ul`
margin-bottom: 16px;
`;

const SectionSeparator = styled.div`
width: 100%;
margin: 24px 0 16px 12px;
padding-top: 16px;
border-top: 2px solid ${colors.textFieldBorder};
`;

const SectionHeading = styled.h3`
font-size: 16px;
font-weight: 600;
color: ${colors.textLead};
margin: 0 0 8px;
`;

class EntryListing extends React.Component {
static propTypes = {
collections: ImmutablePropTypes.iterable.isRequired,
Expand All @@ -29,6 +51,8 @@ class EntryListing extends React.Component {
getUnpublishedEntries: PropTypes.func.isRequired,
getWorkflowStatus: PropTypes.func.isRequired,
filterTerm: PropTypes.string,
sortFields: ImmutablePropTypes.list,
t: PropTypes.func.isRequired,
};

componentDidMount() {
Expand Down Expand Up @@ -58,18 +82,30 @@ class EntryListing extends React.Component {
return { titleField, descriptionField, imageField, remainingFields };
};

getAllEntries = () => {
const { entries, collections, filterTerm } = this.props;
sortEntries = (entries, sortFields, collections) => {
if (!sortFields || sortFields.size === 0) {
return entries;
}

const keys = sortFields.map(v => selectSortDataPath(collections, v.get('key')));
const orders = sortFields.map(v =>
v.get('direction') === SortDirection.Ascending ? 'asc' : 'desc',
);
return fromJS(orderBy(entries.toJS(), keys.toArray(), orders.toArray()));
};

getUnpublishedEntriesList = () => {
const { entries, collections, filterTerm, sortFields } = this.props;
const collectionName = Map.isMap(collections) ? collections.get('name') : null;

if (!collectionName) {
return entries;
return List();
}

const unpublishedEntries = this.props.getUnpublishedEntries(collectionName);

if (!unpublishedEntries || unpublishedEntries.length === 0) {
return entries;
return List();
}

let unpublishedList = List(unpublishedEntries.map(entry => entry));
Expand All @@ -91,25 +127,61 @@ class EntryListing extends React.Component {
publishedSlugs.has(entry.get('slug')),
);

return entries.concat(uniqueUnpublished);
return this.sortEntries(uniqueUnpublished, sortFields, collections);
};

renderCardsForSingleCollection = () => {
const { collections, viewStyle } = this.props;
const allEntries = this.getAllEntries();
const { collections, viewStyle, entries, t } = this.props;
const inferredFields = this.inferFields(collections);
const entryCardProps = { collection: collections, inferredFields, viewStyle };

return allEntries.map((entry, idx) => {
const publishedCards = entries.map((entry, idx) => {
const workflowStatus = this.props.getWorkflowStatus(
collections.get('name'),
entry.get('slug'),
);

return (
<EntryCard
{...entryCardProps}
entry={entry}
workflowStatus={workflowStatus}
key={`published-${idx}`}
/>
);
});

const unpublishedEntries = this.getUnpublishedEntriesList();

if (unpublishedEntries.size === 0) {
return publishedCards;
}

const unpublishedCards = unpublishedEntries.map((entry, idx) => {
const workflowStatus = this.props.getWorkflowStatus(
collections.get('name'),
entry.get('slug'),
);

return (
<EntryCard {...entryCardProps} entry={entry} workflowStatus={workflowStatus} key={idx} />
<EntryCard
{...entryCardProps}
entry={entry}
workflowStatus={workflowStatus}
key={`unpublished-${idx}`}
/>
);
});

return (
<React.Fragment>
{publishedCards}
<SectionSeparator key="separator">
<SectionHeading>{t('collection.entries.unpublishedHeader')}</SectionHeading>
</SectionSeparator>
{unpublishedCards}
</React.Fragment>
);
};

renderCardsForMultipleCollections = () => {
Expand Down Expand Up @@ -148,4 +220,4 @@ class EntryListing extends React.Component {
}
}

export default EntryListing;
export default translate()(EntryListing);
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ exports[`EntriesCollection should render connected component 1`] = `
collections="Map { \\"name\\": \\"pages\\", \\"label\\": \\"Pages\\", \\"folder\\": \\"src/pages\\" }"
cursor="[object Object]"
entries="List [ Map { \\"slug\\": \\"index\\", \\"path\\": \\"src/pages/index.md\\", \\"data\\": Map { \\"title\\": \\"Root\\" } }, Map { \\"slug\\": \\"dir1/index\\", \\"path\\": \\"src/pages/dir1/index.md\\", \\"data\\": Map { \\"title\\": \\"File 1\\" } }, Map { \\"slug\\": \\"dir2/index\\", \\"path\\": \\"src/pages/dir2/index.md\\", \\"data\\": Map { \\"title\\": \\"File 2\\" } } ]"
sortfields=""
/>
</DocumentFragment>
`;
Expand All @@ -18,6 +19,7 @@ exports[`EntriesCollection should render show only immediate children for nested
collections="Map { \\"name\\": \\"pages\\", \\"label\\": \\"Pages\\", \\"folder\\": \\"src/pages\\", \\"nested\\": Map { \\"depth\\": 10, \\"subfolders\\": false } }"
cursor="[object Object]"
entries="List [ Map { \\"slug\\": \\"index\\", \\"path\\": \\"src/pages/index.md\\", \\"data\\": Map { \\"title\\": \\"Root\\" } } ]"
sortfields=""
/>
</DocumentFragment>
`;
Expand All @@ -30,6 +32,7 @@ exports[`EntriesCollection should render with applied filter term for nested col
cursor="[object Object]"
entries="List [ Map { \\"slug\\": \\"dir3/dir4/index\\", \\"path\\": \\"src/pages/dir3/dir4/index.md\\", \\"data\\": Map { \\"title\\": \\"File 4\\" } } ]"
filterterm="dir3/dir4"
sortfields=""
/>
</DocumentFragment>
`;
Expand Down
11 changes: 11 additions & 0 deletions packages/decap-cms-locales/src/en/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,17 @@ const en = {
readyHeader: 'Ready',
currentEntries: '%{smart_count} entry |||| %{smart_count} entries',
},
collection: {
sidebar: {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have collection object above in the file, please don't duplicate it.

collections: 'Collections',
allCollections: 'All Collections',
searchAll: 'Search all',
searchIn: 'Search in',
},
entries: {
unpublishedHeader: 'Unpublished Entries',
},
},
},
};

Expand Down
Loading