decap-cms-core 3.7.1 → 3.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,8 +5,9 @@ import PropTypes from 'prop-types';
5
5
  import React from 'react';
6
6
  import ImmutablePropTypes from 'react-immutable-proptypes';
7
7
  import { Waypoint } from 'react-waypoint';
8
- import { Map } from 'immutable';
8
+ import { Map, List } from 'immutable';
9
9
  import { selectFields, selectInferredField } from '../../../reducers/collections';
10
+ import { filterNestedEntries } from './EntriesCollection';
10
11
  import EntryCard from './EntryCard';
11
12
  import { jsx as ___EmotionJSX } from "@emotion/react";
12
13
  const CardsGrid = /*#__PURE__*/_styled("ul", {
@@ -17,17 +18,20 @@ const CardsGrid = /*#__PURE__*/_styled("ul", {
17
18
  styles: "display:flex;flex-flow:row wrap;list-style-type:none;margin-left:-12px;margin-top:16px;margin-bottom:16px"
18
19
  } : {
19
20
  name: "1dbthoi",
20
- styles: "display:flex;flex-flow:row wrap;list-style-type:none;margin-left:-12px;margin-top:16px;margin-bottom:16px/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL0NvbGxlY3Rpb24vRW50cmllcy9FbnRyeUxpc3RpbmcuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBVTJCIiwiZmlsZSI6Ii4uLy4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL0NvbGxlY3Rpb24vRW50cmllcy9FbnRyeUxpc3RpbmcuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgUHJvcFR5cGVzIGZyb20gJ3Byb3AtdHlwZXMnO1xuaW1wb3J0IFJlYWN0IGZyb20gJ3JlYWN0JztcbmltcG9ydCBJbW11dGFibGVQcm9wVHlwZXMgZnJvbSAncmVhY3QtaW1tdXRhYmxlLXByb3B0eXBlcyc7XG5pbXBvcnQgc3R5bGVkIGZyb20gJ0BlbW90aW9uL3N0eWxlZCc7XG5pbXBvcnQgeyBXYXlwb2ludCB9IGZyb20gJ3JlYWN0LXdheXBvaW50JztcbmltcG9ydCB7IE1hcCB9IGZyb20gJ2ltbXV0YWJsZSc7XG5cbmltcG9ydCB7IHNlbGVjdEZpZWxkcywgc2VsZWN0SW5mZXJyZWRGaWVsZCB9IGZyb20gJy4uLy4uLy4uL3JlZHVjZXJzL2NvbGxlY3Rpb25zJztcbmltcG9ydCBFbnRyeUNhcmQgZnJvbSAnLi9FbnRyeUNhcmQnO1xuXG5jb25zdCBDYXJkc0dyaWQgPSBzdHlsZWQudWxgXG4gIGRpc3BsYXk6IGZsZXg7XG4gIGZsZXgtZmxvdzogcm93IHdyYXA7XG4gIGxpc3Qtc3R5bGUtdHlwZTogbm9uZTtcbiAgbWFyZ2luLWxlZnQ6IC0xMnB4O1xuICBtYXJnaW4tdG9wOiAxNnB4O1xuICBtYXJnaW4tYm90dG9tOiAxNnB4O1xuYDtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgRW50cnlMaXN0aW5nIGV4dGVuZHMgUmVhY3QuQ29tcG9uZW50IHtcbiAgc3RhdGljIHByb3BUeXBlcyA9IHtcbiAgICBjb2xsZWN0aW9uczogSW1tdXRhYmxlUHJvcFR5cGVzLml0ZXJhYmxlLmlzUmVxdWlyZWQsXG4gICAgZW50cmllczogSW1tdXRhYmxlUHJvcFR5cGVzLmxpc3QsXG4gICAgdmlld1N0eWxlOiBQcm9wVHlwZXMuc3RyaW5nLFxuICAgIGN1cnNvcjogUHJvcFR5cGVzLmFueS5pc1JlcXVpcmVkLFxuICAgIGhhbmRsZUN1cnNvckFjdGlvbnM6IFByb3BUeXBlcy5mdW5jLmlzUmVxdWlyZWQsXG4gICAgcGFnZTogUHJvcFR5cGVzLm51bWJlcixcbiAgfTtcblxuICBjb21wb25lbnREaWRNb3VudCgpIHtcbiAgICAvLyBNYW51YWxseSB2YWxpZGF0ZSBQcm9wVHlwZXMgLSBSZWFjdCAxOSBicmVha2luZyBjaGFuZ2VcbiAgICBQcm9wVHlwZXMuY2hlY2tQcm9wVHlwZXMoRW50cnlMaXN0aW5nLnByb3BUeXBlcywgdGhpcy5wcm9wcywgJ3Byb3AnLCAnRW50cnlMaXN0aW5nJyk7XG4gIH1cblxuICBoYXNNb3JlID0gKCkgPT4ge1xuICAgIGNvbnN0IGhhc01vcmUgPSB0aGlzLnByb3BzLmN1cnNvcj8uYWN0aW9ucz8uaGFzKCdhcHBlbmRfbmV4dCcpO1xuICAgIHJldHVybiBoYXNNb3JlO1xuICB9O1xuXG4gIGhhbmRsZUxvYWRNb3JlID0gKCkgPT4ge1xuICAgIGlmICh0aGlzLmhhc01vcmUoKSkge1xuICAgICAgdGhpcy5wcm9wcy5oYW5kbGVDdXJzb3JBY3Rpb25zKCdhcHBlbmRfbmV4dCcpO1xuICAgIH1cbiAgfTtcblxuICBpbmZlckZpZWxkcyA9IGNvbGxlY3Rpb24gPT4ge1xuICAgIGNvbnN0IHRpdGxlRmllbGQgPSBzZWxlY3RJbmZlcnJlZEZpZWxkKGNvbGxlY3Rpb24sICd0aXRsZScpO1xuICAgIGNvbnN0IGRlc2NyaXB0aW9uRmllbGQgPSBzZWxlY3RJbmZlcnJlZEZpZWxkKGNvbGxlY3Rpb24sICdkZXNjcmlwdGlvbicpO1xuICAgIGNvbnN0IGltYWdlRmllbGQgPSBzZWxlY3RJbmZlcnJlZEZpZWxkKGNvbGxlY3Rpb24sICdpbWFnZScpO1xuICAgIGNvbnN0IGZpZWxkcyA9IHNlbGVjdEZpZWxkcyhjb2xsZWN0aW9uKTtcbiAgICBjb25zdCBpbmZlcnJlZEZpZWxkcyA9IFt0aXRsZUZpZWxkLCBkZXNjcmlwdGlvbkZpZWxkLCBpbWFnZUZpZWxkXTtcbiAgICBjb25zdCByZW1haW5pbmdGaWVsZHMgPVxuICAgICAgZmllbGRzICYmIGZpZWxkcy5maWx0ZXIoZiA9PiBpbmZlcnJlZEZpZWxkcy5pbmRleE9mKGYuZ2V0KCduYW1lJykpID09PSAtMSk7XG4gICAgcmV0dXJuIHsgdGl0bGVGaWVsZCwgZGVzY3JpcHRpb25GaWVsZCwgaW1hZ2VGaWVsZCwgcmVtYWluaW5nRmllbGRzIH07XG4gIH07XG5cbiAgcmVuZGVyQ2FyZHNGb3JTaW5nbGVDb2xsZWN0aW9uID0gKCkgPT4ge1xuICAgIGNvbnN0IHsgY29sbGVjdGlvbnMsIGVudHJpZXMsIHZpZXdTdHlsZSB9ID0gdGhpcy5wcm9wcztcbiAgICBjb25zdCBpbmZlcnJlZEZpZWxkcyA9IHRoaXMuaW5mZXJGaWVsZHMoY29sbGVjdGlvbnMpO1xuICAgIGNvbnN0IGVudHJ5Q2FyZFByb3BzID0geyBjb2xsZWN0aW9uOiBjb2xsZWN0aW9ucywgaW5mZXJyZWRGaWVsZHMsIHZpZXdTdHlsZSB9O1xuICAgIHJldHVybiBlbnRyaWVzLm1hcCgoZW50cnksIGlkeCkgPT4gPEVudHJ5Q2FyZCB7Li4uZW50cnlDYXJkUHJvcHN9IGVudHJ5PXtlbnRyeX0ga2V5PXtpZHh9IC8+KTtcbiAgfTtcblxuICByZW5kZXJDYXJkc0Zvck11bHRpcGxlQ29sbGVjdGlvbnMgPSAoKSA9PiB7XG4gICAgY29uc3QgeyBjb2xsZWN0aW9ucywgZW50cmllcyB9ID0gdGhpcy5wcm9wcztcbiAgICBjb25zdCBpc1NpbmdsZUNvbGxlY3Rpb25Jbkxpc3QgPSBjb2xsZWN0aW9ucy5zaXplID09PSAxO1xuICAgIHJldHVybiBlbnRyaWVzLm1hcCgoZW50cnksIGlkeCkgPT4ge1xuICAgICAgY29uc3QgY29sbGVjdGlvbk5hbWUgPSBlbnRyeS5nZXQoJ2NvbGxlY3Rpb24nKTtcbiAgICAgIGNvbnN0IGNvbGxlY3Rpb24gPSBjb2xsZWN0aW9ucy5maW5kKGNvbGwgPT4gY29sbC5nZXQoJ25hbWUnKSA9PT0gY29sbGVjdGlvbk5hbWUpO1xuICAgICAgY29uc3QgY29sbGVjdGlvbkxhYmVsID0gIWlzU2luZ2xlQ29sbGVjdGlvbkluTGlzdCAmJiBjb2xsZWN0aW9uLmdldCgnbGFiZWwnKTtcbiAgICAgIGNvbnN0IGluZmVycmVkRmllbGRzID0gdGhpcy5pbmZlckZpZWxkcyhjb2xsZWN0aW9uKTtcbiAgICAgIGNvbnN0IGVudHJ5Q2FyZFByb3BzID0geyBjb2xsZWN0aW9uLCBlbnRyeSwgaW5mZXJyZWRGaWVsZHMsIGNvbGxlY3Rpb25MYWJlbCB9O1xuICAgICAgcmV0dXJuIDxFbnRyeUNhcmQgey4uLmVudHJ5Q2FyZFByb3BzfSBrZXk9e2lkeH0gLz47XG4gICAgfSk7XG4gIH07XG5cbiAgcmVuZGVyKCkge1xuICAgIGNvbnN0IHsgY29sbGVjdGlvbnMsIHBhZ2UgfSA9IHRoaXMucHJvcHM7XG5cbiAgICByZXR1cm4gKFxuICAgICAgPGRpdj5cbiAgICAgICAgPENhcmRzR3JpZD5cbiAgICAgICAgICB7TWFwLmlzTWFwKGNvbGxlY3Rpb25zKVxuICAgICAgICAgICAgPyB0aGlzLnJlbmRlckNhcmRzRm9yU2luZ2xlQ29sbGVjdGlvbigpXG4gICAgICAgICAgICA6IHRoaXMucmVuZGVyQ2FyZHNGb3JNdWx0aXBsZUNvbGxlY3Rpb25zKCl9XG4gICAgICAgICAge3RoaXMuaGFzTW9yZSgpICYmIDxXYXlwb2ludCBrZXk9e3BhZ2V9IG9uRW50ZXI9e3RoaXMuaGFuZGxlTG9hZE1vcmV9IC8+fVxuICAgICAgICA8L0NhcmRzR3JpZD5cbiAgICAgIDwvZGl2PlxuICAgICk7XG4gIH1cbn1cbiJdfQ== */",
21
+ styles: "display:flex;flex-flow:row wrap;list-style-type:none;margin-left:-12px;margin-top:16px;margin-bottom:16px/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL0NvbGxlY3Rpb24vRW50cmllcy9FbnRyeUxpc3RpbmcuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBVzJCIiwiZmlsZSI6Ii4uLy4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL0NvbGxlY3Rpb24vRW50cmllcy9FbnRyeUxpc3RpbmcuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgUHJvcFR5cGVzIGZyb20gJ3Byb3AtdHlwZXMnO1xuaW1wb3J0IFJlYWN0IGZyb20gJ3JlYWN0JztcbmltcG9ydCBJbW11dGFibGVQcm9wVHlwZXMgZnJvbSAncmVhY3QtaW1tdXRhYmxlLXByb3B0eXBlcyc7XG5pbXBvcnQgc3R5bGVkIGZyb20gJ0BlbW90aW9uL3N0eWxlZCc7XG5pbXBvcnQgeyBXYXlwb2ludCB9IGZyb20gJ3JlYWN0LXdheXBvaW50JztcbmltcG9ydCB7IE1hcCwgTGlzdCB9IGZyb20gJ2ltbXV0YWJsZSc7XG5cbmltcG9ydCB7IHNlbGVjdEZpZWxkcywgc2VsZWN0SW5mZXJyZWRGaWVsZCB9IGZyb20gJy4uLy4uLy4uL3JlZHVjZXJzL2NvbGxlY3Rpb25zJztcbmltcG9ydCB7IGZpbHRlck5lc3RlZEVudHJpZXMgfSBmcm9tICcuL0VudHJpZXNDb2xsZWN0aW9uJztcbmltcG9ydCBFbnRyeUNhcmQgZnJvbSAnLi9FbnRyeUNhcmQnO1xuXG5jb25zdCBDYXJkc0dyaWQgPSBzdHlsZWQudWxgXG4gIGRpc3BsYXk6IGZsZXg7XG4gIGZsZXgtZmxvdzogcm93IHdyYXA7XG4gIGxpc3Qtc3R5bGUtdHlwZTogbm9uZTtcbiAgbWFyZ2luLWxlZnQ6IC0xMnB4O1xuICBtYXJnaW4tdG9wOiAxNnB4O1xuICBtYXJnaW4tYm90dG9tOiAxNnB4O1xuYDtcblxuY2xhc3MgRW50cnlMaXN0aW5nIGV4dGVuZHMgUmVhY3QuQ29tcG9uZW50IHtcbiAgc3RhdGljIHByb3BUeXBlcyA9IHtcbiAgICBjb2xsZWN0aW9uczogSW1tdXRhYmxlUHJvcFR5cGVzLml0ZXJhYmxlLmlzUmVxdWlyZWQsXG4gICAgZW50cmllczogSW1tdXRhYmxlUHJvcFR5cGVzLmxpc3QsXG4gICAgdmlld1N0eWxlOiBQcm9wVHlwZXMuc3RyaW5nLFxuICAgIGN1cnNvcjogUHJvcFR5cGVzLmFueS5pc1JlcXVpcmVkLFxuICAgIGhhbmRsZUN1cnNvckFjdGlvbnM6IFByb3BUeXBlcy5mdW5jLmlzUmVxdWlyZWQsXG4gICAgcGFnZTogUHJvcFR5cGVzLm51bWJlcixcbiAgICBnZXRVbnB1Ymxpc2hlZEVudHJpZXM6IFByb3BUeXBlcy5mdW5jLmlzUmVxdWlyZWQsXG4gICAgZ2V0V29ya2Zsb3dTdGF0dXM6IFByb3BUeXBlcy5mdW5jLmlzUmVxdWlyZWQsXG4gICAgZmlsdGVyVGVybTogUHJvcFR5cGVzLnN0cmluZyxcbiAgfTtcblxuICBjb21wb25lbnREaWRNb3VudCgpIHtcbiAgICAvLyBNYW51YWxseSB2YWxpZGF0ZSBQcm9wVHlwZXMgLSBSZWFjdCAxOSBicmVha2luZyBjaGFuZ2VcbiAgICBQcm9wVHlwZXMuY2hlY2tQcm9wVHlwZXMoRW50cnlMaXN0aW5nLnByb3BUeXBlcywgdGhpcy5wcm9wcywgJ3Byb3AnLCAnRW50cnlMaXN0aW5nJyk7XG4gIH1cblxuICBoYXNNb3JlID0gKCkgPT4ge1xuICAgIGNvbnN0IGhhc01vcmUgPSB0aGlzLnByb3BzLmN1cnNvcj8uYWN0aW9ucz8uaGFzKCdhcHBlbmRfbmV4dCcpO1xuICAgIHJldHVybiBoYXNNb3JlO1xuICB9O1xuXG4gIGhhbmRsZUxvYWRNb3JlID0gKCkgPT4ge1xuICAgIGlmICh0aGlzLmhhc01vcmUoKSkge1xuICAgICAgdGhpcy5wcm9wcy5oYW5kbGVDdXJzb3JBY3Rpb25zKCdhcHBlbmRfbmV4dCcpO1xuICAgIH1cbiAgfTtcblxuICBpbmZlckZpZWxkcyA9IGNvbGxlY3Rpb24gPT4ge1xuICAgIGNvbnN0IHRpdGxlRmllbGQgPSBzZWxlY3RJbmZlcnJlZEZpZWxkKGNvbGxlY3Rpb24sICd0aXRsZScpO1xuICAgIGNvbnN0IGRlc2NyaXB0aW9uRmllbGQgPSBzZWxlY3RJbmZlcnJlZEZpZWxkKGNvbGxlY3Rpb24sICdkZXNjcmlwdGlvbicpO1xuICAgIGNvbnN0IGltYWdlRmllbGQgPSBzZWxlY3RJbmZlcnJlZEZpZWxkKGNvbGxlY3Rpb24sICdpbWFnZScpO1xuICAgIGNvbnN0IGZpZWxkcyA9IHNlbGVjdEZpZWxkcyhjb2xsZWN0aW9uKTtcbiAgICBjb25zdCBpbmZlcnJlZEZpZWxkcyA9IFt0aXRsZUZpZWxkLCBkZXNjcmlwdGlvbkZpZWxkLCBpbWFnZUZpZWxkXTtcbiAgICBjb25zdCByZW1haW5pbmdGaWVsZHMgPVxuICAgICAgZmllbGRzICYmIGZpZWxkcy5maWx0ZXIoZiA9PiBpbmZlcnJlZEZpZWxkcy5pbmRleE9mKGYuZ2V0KCduYW1lJykpID09PSAtMSk7XG4gICAgcmV0dXJuIHsgdGl0bGVGaWVsZCwgZGVzY3JpcHRpb25GaWVsZCwgaW1hZ2VGaWVsZCwgcmVtYWluaW5nRmllbGRzIH07XG4gIH07XG5cbiAgZ2V0QWxsRW50cmllcyA9ICgpID0+IHtcbiAgICBjb25zdCB7IGVudHJpZXMsIGNvbGxlY3Rpb25zLCBmaWx0ZXJUZXJtIH0gPSB0aGlzLnByb3BzO1xuICAgIGNvbnN0IGNvbGxlY3Rpb25OYW1lID0gTWFwLmlzTWFwKGNvbGxlY3Rpb25zKSA/IGNvbGxlY3Rpb25zLmdldCgnbmFtZScpIDogbnVsbDtcblxuICAgIGlmICghY29sbGVjdGlvbk5hbWUpIHtcbiAgICAgIHJldHVybiBlbnRyaWVzO1xuICAgIH1cblxuICAgIGNvbnN0IHVucHVibGlzaGVkRW50cmllcyA9IHRoaXMucHJvcHMuZ2V0VW5wdWJsaXNoZWRFbnRyaWVzKGNvbGxlY3Rpb25OYW1lKTtcblxuICAgIGlmICghdW5wdWJsaXNoZWRFbnRyaWVzIHx8IHVucHVibGlzaGVkRW50cmllcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiBlbnRyaWVzO1xuICAgIH1cblxuICAgIGxldCB1bnB1Ymxpc2hlZExpc3QgPSBMaXN0KHVucHVibGlzaGVkRW50cmllcy5tYXAoZW50cnkgPT4gZW50cnkpKTtcblxuICAgIGlmIChjb2xsZWN0aW9ucy5oYXMoJ25lc3RlZCcpICYmIGZpbHRlclRlcm0pIHtcbiAgICAgIGNvbnN0IGNvbGxlY3Rpb25Gb2xkZXIgPSBjb2xsZWN0aW9ucy5nZXQoJ2ZvbGRlcicpO1xuICAgICAgY29uc3Qgc3ViZm9sZGVycyA9IGNvbGxlY3Rpb25zLmdldCgnbmVzdGVkJykuZ2V0KCdzdWJmb2xkZXJzJykgIT09IGZhbHNlO1xuXG4gICAgICB1bnB1Ymxpc2hlZExpc3QgPSBmaWx0ZXJOZXN0ZWRFbnRyaWVzKFxuICAgICAgICBmaWx0ZXJUZXJtLFxuICAgICAgICBjb2xsZWN0aW9uRm9sZGVyLFxuICAgICAgICB1bnB1Ymxpc2hlZExpc3QsXG4gICAgICAgIHN1YmZvbGRlcnMsXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IHB1Ymxpc2hlZFNsdWdzID0gZW50cmllcy5tYXAoZW50cnkgPT4gZW50cnkuZ2V0KCdzbHVnJykpLnRvU2V0KCk7XG4gICAgY29uc3QgdW5pcXVlVW5wdWJsaXNoZWQgPSB1bnB1Ymxpc2hlZExpc3QuZmlsdGVyTm90KGVudHJ5ID0+XG4gICAgICBwdWJsaXNoZWRTbHVncy5oYXMoZW50cnkuZ2V0KCdzbHVnJykpLFxuICAgICk7XG5cbiAgICByZXR1cm4gZW50cmllcy5jb25jYXQodW5pcXVlVW5wdWJsaXNoZWQpO1xuICB9O1xuXG4gIHJlbmRlckNhcmRzRm9yU2luZ2xlQ29sbGVjdGlvbiA9ICgpID0+IHtcbiAgICBjb25zdCB7IGNvbGxlY3Rpb25zLCB2aWV3U3R5bGUgfSA9IHRoaXMucHJvcHM7XG4gICAgY29uc3QgYWxsRW50cmllcyA9IHRoaXMuZ2V0QWxsRW50cmllcygpO1xuICAgIGNvbnN0IGluZmVycmVkRmllbGRzID0gdGhpcy5pbmZlckZpZWxkcyhjb2xsZWN0aW9ucyk7XG4gICAgY29uc3QgZW50cnlDYXJkUHJvcHMgPSB7IGNvbGxlY3Rpb246IGNvbGxlY3Rpb25zLCBpbmZlcnJlZEZpZWxkcywgdmlld1N0eWxlIH07XG5cbiAgICByZXR1cm4gYWxsRW50cmllcy5tYXAoKGVudHJ5LCBpZHgpID0+IHtcbiAgICAgIGNvbnN0IHdvcmtmbG93U3RhdHVzID0gdGhpcy5wcm9wcy5nZXRXb3JrZmxvd1N0YXR1cyhcbiAgICAgICAgY29sbGVjdGlvbnMuZ2V0KCduYW1lJyksXG4gICAgICAgIGVudHJ5LmdldCgnc2x1ZycpLFxuICAgICAgKTtcblxuICAgICAgcmV0dXJuIChcbiAgICAgICAgPEVudHJ5Q2FyZCB7Li4uZW50cnlDYXJkUHJvcHN9IGVudHJ5PXtlbnRyeX0gd29ya2Zsb3dTdGF0dXM9e3dvcmtmbG93U3RhdHVzfSBrZXk9e2lkeH0gLz5cbiAgICAgICk7XG4gICAgfSk7XG4gIH07XG5cbiAgcmVuZGVyQ2FyZHNGb3JNdWx0aXBsZUNvbGxlY3Rpb25zID0gKCkgPT4ge1xuICAgIGNvbnN0IHsgY29sbGVjdGlvbnMsIGVudHJpZXMgfSA9IHRoaXMucHJvcHM7XG4gICAgY29uc3QgaXNTaW5nbGVDb2xsZWN0aW9uSW5MaXN0ID0gY29sbGVjdGlvbnMuc2l6ZSA9PT0gMTtcbiAgICByZXR1cm4gZW50cmllcy5tYXAoKGVudHJ5LCBpZHgpID0+IHtcbiAgICAgIGNvbnN0IGNvbGxlY3Rpb25OYW1lID0gZW50cnkuZ2V0KCdjb2xsZWN0aW9uJyk7XG4gICAgICBjb25zdCBjb2xsZWN0aW9uID0gY29sbGVjdGlvbnMuZmluZChjb2xsID0+IGNvbGwuZ2V0KCduYW1lJykgPT09IGNvbGxlY3Rpb25OYW1lKTtcbiAgICAgIGNvbnN0IGNvbGxlY3Rpb25MYWJlbCA9ICFpc1NpbmdsZUNvbGxlY3Rpb25Jbkxpc3QgJiYgY29sbGVjdGlvbi5nZXQoJ2xhYmVsJyk7XG4gICAgICBjb25zdCBpbmZlcnJlZEZpZWxkcyA9IHRoaXMuaW5mZXJGaWVsZHMoY29sbGVjdGlvbik7XG4gICAgICBjb25zdCB3b3JrZmxvd1N0YXR1cyA9IHRoaXMucHJvcHMuZ2V0V29ya2Zsb3dTdGF0dXMoY29sbGVjdGlvbk5hbWUsIGVudHJ5LmdldCgnc2x1ZycpKTtcbiAgICAgIGNvbnN0IGVudHJ5Q2FyZFByb3BzID0ge1xuICAgICAgICBjb2xsZWN0aW9uLFxuICAgICAgICBlbnRyeSxcbiAgICAgICAgaW5mZXJyZWRGaWVsZHMsXG4gICAgICAgIGNvbGxlY3Rpb25MYWJlbCxcbiAgICAgICAgd29ya2Zsb3dTdGF0dXMsXG4gICAgICB9O1xuICAgICAgcmV0dXJuIDxFbnRyeUNhcmQgey4uLmVudHJ5Q2FyZFByb3BzfSBrZXk9e2lkeH0gLz47XG4gICAgfSk7XG4gIH07XG5cbiAgcmVuZGVyKCkge1xuICAgIGNvbnN0IHsgY29sbGVjdGlvbnMsIHBhZ2UgfSA9IHRoaXMucHJvcHM7XG5cbiAgICByZXR1cm4gKFxuICAgICAgPGRpdj5cbiAgICAgICAgPENhcmRzR3JpZD5cbiAgICAgICAgICB7TWFwLmlzTWFwKGNvbGxlY3Rpb25zKVxuICAgICAgICAgICAgPyB0aGlzLnJlbmRlckNhcmRzRm9yU2luZ2xlQ29sbGVjdGlvbigpXG4gICAgICAgICAgICA6IHRoaXMucmVuZGVyQ2FyZHNGb3JNdWx0aXBsZUNvbGxlY3Rpb25zKCl9XG4gICAgICAgICAge3RoaXMuaGFzTW9yZSgpICYmIDxXYXlwb2ludCBrZXk9e3BhZ2V9IG9uRW50ZXI9e3RoaXMuaGFuZGxlTG9hZE1vcmV9IC8+fVxuICAgICAgICA8L0NhcmRzR3JpZD5cbiAgICAgIDwvZGl2PlxuICAgICk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgRW50cnlMaXN0aW5nO1xuIl19 */",
21
22
  toString: _EMOTION_STRINGIFIED_CSS_ERROR__
22
23
  });
23
- export default class EntryListing extends React.Component {
24
+ class EntryListing extends React.Component {
24
25
  static propTypes = {
25
26
  collections: ImmutablePropTypes.iterable.isRequired,
26
27
  entries: ImmutablePropTypes.list,
27
28
  viewStyle: PropTypes.string,
28
29
  cursor: PropTypes.any.isRequired,
29
30
  handleCursorActions: PropTypes.func.isRequired,
30
- page: PropTypes.number
31
+ page: PropTypes.number,
32
+ getUnpublishedEntries: PropTypes.func.isRequired,
33
+ getWorkflowStatus: PropTypes.func.isRequired,
34
+ filterTerm: PropTypes.string
31
35
  };
32
36
  componentDidMount() {
33
37
  // Manually validate PropTypes - React 19 breaking change
@@ -56,22 +60,50 @@ export default class EntryListing extends React.Component {
56
60
  remainingFields
57
61
  };
58
62
  };
63
+ getAllEntries = () => {
64
+ const {
65
+ entries,
66
+ collections,
67
+ filterTerm
68
+ } = this.props;
69
+ const collectionName = Map.isMap(collections) ? collections.get('name') : null;
70
+ if (!collectionName) {
71
+ return entries;
72
+ }
73
+ const unpublishedEntries = this.props.getUnpublishedEntries(collectionName);
74
+ if (!unpublishedEntries || unpublishedEntries.length === 0) {
75
+ return entries;
76
+ }
77
+ let unpublishedList = List(unpublishedEntries.map(entry => entry));
78
+ if (collections.has('nested') && filterTerm) {
79
+ const collectionFolder = collections.get('folder');
80
+ const subfolders = collections.get('nested').get('subfolders') !== false;
81
+ unpublishedList = filterNestedEntries(filterTerm, collectionFolder, unpublishedList, subfolders);
82
+ }
83
+ const publishedSlugs = entries.map(entry => entry.get('slug')).toSet();
84
+ const uniqueUnpublished = unpublishedList.filterNot(entry => publishedSlugs.has(entry.get('slug')));
85
+ return entries.concat(uniqueUnpublished);
86
+ };
59
87
  renderCardsForSingleCollection = () => {
60
88
  const {
61
89
  collections,
62
- entries,
63
90
  viewStyle
64
91
  } = this.props;
92
+ const allEntries = this.getAllEntries();
65
93
  const inferredFields = this.inferFields(collections);
66
94
  const entryCardProps = {
67
95
  collection: collections,
68
96
  inferredFields,
69
97
  viewStyle
70
98
  };
71
- return entries.map((entry, idx) => ___EmotionJSX(EntryCard, _extends({}, entryCardProps, {
72
- entry: entry,
73
- key: idx
74
- })));
99
+ return allEntries.map((entry, idx) => {
100
+ const workflowStatus = this.props.getWorkflowStatus(collections.get('name'), entry.get('slug'));
101
+ return ___EmotionJSX(EntryCard, _extends({}, entryCardProps, {
102
+ entry: entry,
103
+ workflowStatus: workflowStatus,
104
+ key: idx
105
+ }));
106
+ });
75
107
  };
76
108
  renderCardsForMultipleCollections = () => {
77
109
  const {
@@ -84,11 +116,13 @@ export default class EntryListing extends React.Component {
84
116
  const collection = collections.find(coll => coll.get('name') === collectionName);
85
117
  const collectionLabel = !isSingleCollectionInList && collection.get('label');
86
118
  const inferredFields = this.inferFields(collection);
119
+ const workflowStatus = this.props.getWorkflowStatus(collectionName, entry.get('slug'));
87
120
  const entryCardProps = {
88
121
  collection,
89
122
  entry,
90
123
  inferredFields,
91
- collectionLabel
124
+ collectionLabel,
125
+ workflowStatus
92
126
  };
93
127
  return ___EmotionJSX(EntryCard, _extends({}, entryCardProps, {
94
128
  key: idx
@@ -105,4 +139,5 @@ export default class EntryListing extends React.Component {
105
139
  onEnter: this.handleLoadMore
106
140
  })));
107
141
  }
108
- }
142
+ }
143
+ export default EntryListing;
@@ -44,8 +44,8 @@ function buildIssueTemplate({
44
44
  let version = '';
45
45
  if (typeof DECAP_CMS_VERSION === 'string') {
46
46
  version = `decap-cms@${DECAP_CMS_VERSION}`;
47
- } else if (typeof "3.7.2" === 'string') {
48
- version = `decap-cms-app@${"3.7.2"}`;
47
+ } else if (typeof "3.8.0" === 'string') {
48
+ version = `decap-cms-app@${"3.8.0"}`;
49
49
  }
50
50
  const template = getIssueTemplate({
51
51
  version,
@@ -244,6 +244,20 @@ function getConfigSchema() {
244
244
  type: 'string',
245
245
  examples: ['https://example.com/images/logo.svg']
246
246
  },
247
+ // Deprecated, replaced by `logo.src`
248
+ logo: {
249
+ type: 'object',
250
+ properties: {
251
+ src: {
252
+ type: 'string',
253
+ examples: ['https://example.com/images/logo.svg']
254
+ },
255
+ show_in_header: {
256
+ type: 'boolean'
257
+ }
258
+ },
259
+ required: ['src']
260
+ },
247
261
  show_preview_links: {
248
262
  type: 'boolean'
249
263
  },
@@ -185,6 +185,19 @@ export function formatI18nBackup(i18nBackup, formatRawData) {
185
185
  }, {});
186
186
  return i18n;
187
187
  }
188
+ function applyDefaultI18nValues(collection, value, defaultLocaleValue) {
189
+ if (collection.get('fields') === undefined) {
190
+ return;
191
+ }
192
+ collection.get('fields').forEach(field => {
193
+ if (field && field.get(I18N) === I18N_FIELD.DUPLICATE) {
194
+ const data = value.data[field.get('name')];
195
+ if (!data) {
196
+ value.data[field.get('name')] = defaultLocaleValue.data[field.get('name')];
197
+ }
198
+ }
199
+ });
200
+ }
188
201
  function mergeValues(collection, structure, defaultLocale, values) {
189
202
  let defaultEntry = values.find(e => e.locale === defaultLocale);
190
203
  if (!defaultEntry) {
@@ -196,6 +209,9 @@ function mergeValues(collection, structure, defaultLocale, values) {
196
209
  value
197
210
  }) => {
198
211
  const dataPath = getLocaleDataPath(locale);
212
+ if (defaultEntry) {
213
+ applyDefaultI18nValues(collection, value, defaultEntry.value);
214
+ }
199
215
  return set(acc, dataPath, value.data);
200
216
  }, {});
201
217
  const path = normalizeFilePath(structure, defaultEntry.value.path, defaultLocale);
package/index.d.ts CHANGED
@@ -384,7 +384,11 @@ declare module 'decap-cms-core' {
384
384
  locale?: string;
385
385
  site_url?: string;
386
386
  display_url?: string;
387
- logo_url?: string;
387
+ logo_url?: string; // Deprecated, replaced by `logo.src`
388
+ logo?: {
389
+ src: string;
390
+ show_in_header?: boolean;
391
+ };
388
392
  show_preview_links?: boolean;
389
393
  media_folder?: string;
390
394
  public_folder?: string;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "decap-cms-core",
3
3
  "description": "Decap CMS core application, see decap-cms package for the main distribution.",
4
- "version": "3.7.1",
4
+ "version": "3.8.0",
5
5
  "repository": "https://github.com/decaporg/decap-cms/tree/main/packages/decap-cms-core",
6
6
  "bugs": "https://github.com/decaporg/decap-cms/issues",
7
7
  "module": "dist/esm/index.js",
@@ -100,5 +100,5 @@
100
100
  "browser": {
101
101
  "path": "path-browserify"
102
102
  },
103
- "gitHead": "bfe122aee875ceaaf9f132110db7f8797eedfc5b"
103
+ "gitHead": "d3465f53b7f056ad5d872948a07eaa8e4ae63315"
104
104
  }
@@ -188,6 +188,8 @@ class App extends React.Component {
188
188
  openMediaLibrary={openMediaLibrary}
189
189
  hasWorkflow={hasWorkflow}
190
190
  displayUrl={config.display_url}
191
+ logoUrl={config.logo_url} // Deprecated, replaced by `logo.src`
192
+ logo={config.logo}
191
193
  isTestRepo={config.backend.name === 'test-repo'}
192
194
  showMediaButton={showMediaButton}
193
195
  />
@@ -114,6 +114,19 @@ const AppHeaderNavList = styled.ul`
114
114
  list-style: none;
115
115
  `;
116
116
 
117
+ const AppHeaderLogo = styled.li`
118
+ display: flex;
119
+ align-items: center;
120
+
121
+ img {
122
+ padding: 12px 20px;
123
+ max-height: 56px;
124
+ max-width: 300px;
125
+ object-fit: contain;
126
+ object-position: center;
127
+ }
128
+ `;
129
+
117
130
  class Header extends React.Component {
118
131
  static propTypes = {
119
132
  user: PropTypes.object.isRequired,
@@ -123,6 +136,11 @@ class Header extends React.Component {
123
136
  openMediaLibrary: PropTypes.func.isRequired,
124
137
  hasWorkflow: PropTypes.bool.isRequired,
125
138
  displayUrl: PropTypes.string,
139
+ logoUrl: PropTypes.string, // Deprecated, replaced by `logo.src`
140
+ logo: PropTypes.shape({
141
+ src: PropTypes.string.isRequired,
142
+ show_in_header: PropTypes.bool,
143
+ }),
126
144
  isTestRepo: PropTypes.bool,
127
145
  t: PropTypes.func.isRequired,
128
146
  checkBackendStatus: PropTypes.func.isRequired,
@@ -158,6 +176,8 @@ class Header extends React.Component {
158
176
  openMediaLibrary,
159
177
  hasWorkflow,
160
178
  displayUrl,
179
+ logoUrl, // Deprecated, replaced by `logo.src`
180
+ logo,
161
181
  isTestRepo,
162
182
  t,
163
183
  showMediaButton,
@@ -167,11 +187,18 @@ class Header extends React.Component {
167
187
  .filter(collection => collection.get('create'))
168
188
  .toList();
169
189
 
190
+ const shouldShowLogo = logo?.show_in_header && logo?.src;
191
+
170
192
  return (
171
193
  <AppHeader>
172
194
  <AppHeaderContent>
173
195
  <nav>
174
196
  <AppHeaderNavList>
197
+ {shouldShowLogo && (
198
+ <AppHeaderLogo>
199
+ <img src={logo?.src || logoUrl} alt="Logo" />
200
+ </AppHeaderLogo>
201
+ )}
175
202
  <li>
176
203
  <AppHeaderNavLink
177
204
  to="/"
@@ -26,6 +26,9 @@ function Entries({
26
26
  handleCursorActions,
27
27
  t,
28
28
  page,
29
+ getWorkflowStatus,
30
+ getUnpublishedEntries,
31
+ filterTerm,
29
32
  }) {
30
33
  const loadingMessages = [
31
34
  t('collection.entries.loadingEntries'),
@@ -48,6 +51,9 @@ function Entries({
48
51
  cursor={cursor}
49
52
  handleCursorActions={handleCursorActions}
50
53
  page={page}
54
+ getWorkflowStatus={getWorkflowStatus}
55
+ getUnpublishedEntries={getUnpublishedEntries}
56
+ filterTerm={filterTerm}
51
57
  />
52
58
  {isFetching && page !== undefined && entries.size > 0 ? (
53
59
  <PaginationMessage>{t('collection.entries.loadingEntries')}</PaginationMessage>
@@ -68,6 +74,9 @@ Entries.propTypes = {
68
74
  cursor: PropTypes.any.isRequired,
69
75
  handleCursorActions: PropTypes.func.isRequired,
70
76
  t: PropTypes.func.isRequired,
77
+ getWorkflowStatus: PropTypes.func,
78
+ getUnpublishedEntries: PropTypes.func,
79
+ filterTerm: PropTypes.string,
71
80
  };
72
81
 
73
82
  export default translate()(Entries);
@@ -12,12 +12,14 @@ import {
12
12
  loadEntries as actionLoadEntries,
13
13
  traverseCollectionCursor as actionTraverseCollectionCursor,
14
14
  } from '../../../actions/entries';
15
+ import { loadUnpublishedEntries } from '../../../actions/editorialWorkflow';
15
16
  import {
16
17
  selectEntries,
17
18
  selectEntriesLoaded,
18
19
  selectIsFetching,
19
20
  selectGroups,
20
21
  } from '../../../reducers/entries';
22
+ import { selectUnpublishedEntry, selectUnpublishedEntriesByStatus } from '../../../reducers';
21
23
  import { selectCollectionEntriesCursor } from '../../../reducers/cursors';
22
24
  import Entries from './Entries';
23
25
 
@@ -61,6 +63,7 @@ function withGroups(groups, entries, EntriesToRender, t) {
61
63
  export class EntriesCollection extends React.Component {
62
64
  static propTypes = {
63
65
  collection: ImmutablePropTypes.map.isRequired,
66
+ collections: ImmutablePropTypes.iterable,
64
67
  page: PropTypes.number,
65
68
  entries: ImmutablePropTypes.list,
66
69
  groups: PropTypes.array,
@@ -70,23 +73,57 @@ export class EntriesCollection extends React.Component {
70
73
  loadEntries: PropTypes.func.isRequired,
71
74
  traverseCollectionCursor: PropTypes.func.isRequired,
72
75
  entriesLoaded: PropTypes.bool,
76
+ loadUnpublishedEntries: PropTypes.func.isRequired,
77
+ unpublishedEntriesLoaded: PropTypes.bool,
78
+ isEditorialWorkflowEnabled: PropTypes.bool,
79
+ getWorkflowStatus: PropTypes.func.isRequired,
80
+ getUnpublishedEntries: PropTypes.func.isRequired,
73
81
  };
74
82
 
75
83
  componentDidMount() {
76
84
  // Manually validate PropTypes - React 19 breaking change
77
85
  PropTypes.checkPropTypes(EntriesCollection.propTypes, this.props, 'prop', 'EntriesCollection');
78
86
 
79
- const { collection, entriesLoaded, loadEntries } = this.props;
87
+ const {
88
+ collection,
89
+ collections,
90
+ entriesLoaded,
91
+ loadEntries,
92
+ unpublishedEntriesLoaded,
93
+ loadUnpublishedEntries,
94
+ isEditorialWorkflowEnabled,
95
+ } = this.props;
96
+
80
97
  if (collection && !entriesLoaded) {
81
98
  loadEntries(collection);
82
99
  }
100
+
101
+ if (isEditorialWorkflowEnabled && !unpublishedEntriesLoaded) {
102
+ loadUnpublishedEntries(collections);
103
+ }
83
104
  }
84
105
 
85
106
  componentDidUpdate(prevProps) {
86
- const { collection, entriesLoaded, loadEntries } = this.props;
107
+ const {
108
+ collection,
109
+ collections,
110
+ entriesLoaded,
111
+ loadEntries,
112
+ unpublishedEntriesLoaded,
113
+ loadUnpublishedEntries,
114
+ isEditorialWorkflowEnabled,
115
+ } = this.props;
116
+
87
117
  if (collection !== prevProps.collection && !entriesLoaded) {
88
118
  loadEntries(collection);
89
119
  }
120
+
121
+ if (
122
+ isEditorialWorkflowEnabled &&
123
+ (!unpublishedEntriesLoaded || collection !== prevProps.collection)
124
+ ) {
125
+ loadUnpublishedEntries(collections);
126
+ }
90
127
  }
91
128
 
92
129
  handleCursorActions = (cursor, action) => {
@@ -95,7 +132,19 @@ export class EntriesCollection extends React.Component {
95
132
  };
96
133
 
97
134
  render() {
98
- const { collection, entries, groups, isFetching, viewStyle, cursor, page, t } = this.props;
135
+ const {
136
+ collection,
137
+ entries,
138
+ groups,
139
+ isFetching,
140
+ viewStyle,
141
+ cursor,
142
+ page,
143
+ t,
144
+ getWorkflowStatus,
145
+ getUnpublishedEntries,
146
+ filterTerm,
147
+ } = this.props;
99
148
 
100
149
  const EntriesToRender = ({ entries }) => {
101
150
  return (
@@ -108,6 +157,9 @@ export class EntriesCollection extends React.Component {
108
157
  cursor={cursor}
109
158
  handleCursorActions={partial(this.handleCursorActions, cursor)}
110
159
  page={page}
160
+ getWorkflowStatus={getWorkflowStatus}
161
+ getUnpublishedEntries={getUnpublishedEntries}
162
+ filterTerm={filterTerm}
111
163
  />
112
164
  );
113
165
  };
@@ -150,6 +202,8 @@ function mapStateToProps(state, ownProps) {
150
202
  const { collection, viewStyle, filterTerm } = ownProps;
151
203
  const page = state.entries.getIn(['pages', collection.get('name'), 'page']);
152
204
 
205
+ const collections = state.collections;
206
+
153
207
  let entries = selectEntries(state.entries, collection);
154
208
  const groups = selectGroups(state.entries, collection);
155
209
 
@@ -168,12 +222,54 @@ function mapStateToProps(state, ownProps) {
168
222
  const rawCursor = selectCollectionEntriesCursor(state.cursors, collection.get('name'));
169
223
  const cursor = Cursor.create(rawCursor).clearData();
170
224
 
171
- return { collection, page, entries, groups, entriesLoaded, isFetching, viewStyle, cursor };
225
+ const isEditorialWorkflowEnabled = state.config?.publish_mode === 'editorial_workflow';
226
+ const unpublishedEntriesLoaded = isEditorialWorkflowEnabled
227
+ ? !!state.editorialWorkflow?.getIn(['pages', 'ids'], false)
228
+ : true;
229
+
230
+ return {
231
+ collection,
232
+ collections,
233
+ page,
234
+ entries,
235
+ groups,
236
+ entriesLoaded,
237
+ isFetching,
238
+ viewStyle,
239
+ cursor,
240
+ unpublishedEntriesLoaded,
241
+ isEditorialWorkflowEnabled,
242
+ getWorkflowStatus: (collectionName, slug) => {
243
+ const unpublishedEntry = selectUnpublishedEntry(state, collectionName, slug);
244
+ return unpublishedEntry ? unpublishedEntry.get('status') : null;
245
+ },
246
+ getUnpublishedEntries: collectionName => {
247
+ if (!isEditorialWorkflowEnabled) return [];
248
+
249
+ const allStatuses = ['draft', 'pending_review', 'pending_publish'];
250
+ const unpublishedEntries = [];
251
+
252
+ allStatuses.forEach(statusKey => {
253
+ const entriesForStatus = selectUnpublishedEntriesByStatus(state, statusKey);
254
+ if (entriesForStatus) {
255
+ entriesForStatus.forEach(entry => {
256
+ if (entry.get('collection') === collectionName) {
257
+ const entryWithCollection = entry.set('collection', collectionName);
258
+ unpublishedEntries.push(entryWithCollection);
259
+ }
260
+ });
261
+ }
262
+ });
263
+
264
+ return unpublishedEntries;
265
+ },
266
+ };
172
267
  }
173
268
 
174
269
  const mapDispatchToProps = {
175
270
  loadEntries: actionLoadEntries,
176
271
  traverseCollectionCursor: actionTraverseCollectionCursor,
272
+ loadUnpublishedEntries: collections => loadUnpublishedEntries(collections),
177
273
  };
178
274
 
179
275
  const ConnectedEntriesCollection = connect(mapStateToProps, mapDispatchToProps)(EntriesCollection);
@@ -3,6 +3,7 @@ import styled from '@emotion/styled';
3
3
  import { connect } from 'react-redux';
4
4
  import { Link } from 'react-router-dom';
5
5
  import { colors, colorsRaw, components, lengths, zIndex } from 'decap-cms-ui-default';
6
+ import { translate } from 'react-polyglot';
6
7
 
7
8
  import { boundGetAsset } from '../../../actions/media';
8
9
  import { VIEW_STYLE_LIST, VIEW_STYLE_GRID } from '../../../constants/collectionViews';
@@ -56,10 +57,14 @@ const CollectionLabel = styled.h2`
56
57
 
57
58
  const ListCardTitle = styled.h2`
58
59
  margin-bottom: 0;
60
+ display: flex;
61
+ justify-content: space-between;
59
62
  `;
60
63
 
61
64
  const CardHeading = styled.h2`
62
65
  margin: 0 0 2px;
66
+ display: flex;
67
+ justify-content: space-between;
63
68
  `;
64
69
 
65
70
  const CardBody = styled.div`
@@ -89,6 +94,43 @@ const CardImage = styled.div`
89
94
  height: 150px;
90
95
  `;
91
96
 
97
+ const TitleIcons = styled.div`
98
+ display: flex;
99
+ align-items: center;
100
+ gap: 8px;
101
+ `;
102
+
103
+ const WorkflowBadge = styled.span`
104
+ padding: 2px 6px;
105
+ border-radius: 3px;
106
+ font-size: 11px;
107
+ text-transform: uppercase;
108
+ background-color: ${props => {
109
+ switch (props.status) {
110
+ case 'draft':
111
+ return colors.statusDraftBackground;
112
+ case 'pending_review':
113
+ return colors.statusReviewBackground;
114
+ case 'pending_publish':
115
+ return colors.statusReadyBackground;
116
+ default:
117
+ return colors.background;
118
+ }
119
+ }};
120
+ color: ${props => {
121
+ switch (props.status) {
122
+ case 'draft':
123
+ return colors.statusDraftText;
124
+ case 'pending_review':
125
+ return colors.statusReviewText;
126
+ case 'pending_publish':
127
+ return colors.statusReadyText;
128
+ default:
129
+ return colors.text;
130
+ }
131
+ }};
132
+ `;
133
+
92
134
  function EntryCard({
93
135
  path,
94
136
  summary,
@@ -96,14 +138,38 @@ function EntryCard({
96
138
  imageField,
97
139
  collectionLabel,
98
140
  viewStyle = VIEW_STYLE_LIST,
141
+ workflowStatus,
99
142
  getAsset,
143
+ t,
100
144
  }) {
145
+ function getStatusLabel(status) {
146
+ switch (status) {
147
+ case 'pending_review':
148
+ return t('editor.editorToolbar.inReview');
149
+ case 'pending_publish':
150
+ return t('editor.editorToolbar.ready');
151
+ case 'draft':
152
+ return t('editor.editorToolbar.draft');
153
+ default:
154
+ return status;
155
+ }
156
+ }
157
+
101
158
  if (viewStyle === VIEW_STYLE_LIST) {
102
159
  return (
103
160
  <ListCard>
104
161
  <ListCardLink to={path}>
105
162
  {collectionLabel ? <CollectionLabel>{collectionLabel}</CollectionLabel> : null}
106
- <ListCardTitle>{summary}</ListCardTitle>
163
+ <ListCardTitle>
164
+ {summary}
165
+ <TitleIcons>
166
+ {workflowStatus && (
167
+ <WorkflowBadge status={workflowStatus}>
168
+ {getStatusLabel(workflowStatus)}
169
+ </WorkflowBadge>
170
+ )}
171
+ </TitleIcons>
172
+ </ListCardTitle>
107
173
  </ListCardLink>
108
174
  </ListCard>
109
175
  );
@@ -115,7 +181,16 @@ function EntryCard({
115
181
  <GridCardLink to={path}>
116
182
  <CardBody hasImage={image}>
117
183
  {collectionLabel ? <CollectionLabel>{collectionLabel}</CollectionLabel> : null}
118
- <CardHeading>{summary}</CardHeading>
184
+ <CardHeading>
185
+ {summary}
186
+ <TitleIcons>
187
+ {workflowStatus && (
188
+ <WorkflowBadge status={workflowStatus}>
189
+ {getStatusLabel(workflowStatus)}
190
+ </WorkflowBadge>
191
+ )}
192
+ </TitleIcons>
193
+ </CardHeading>
119
194
  </CardBody>
120
195
  {image ? <CardImage src={getAsset(image, imageField).toString()} /> : null}
121
196
  </GridCardLink>
@@ -162,6 +237,10 @@ function mergeProps(stateProps, dispatchProps, ownProps) {
162
237
  };
163
238
  }
164
239
 
165
- const ConnectedEntryCard = connect(mapStateToProps, mapDispatchToProps, mergeProps)(EntryCard);
240
+ const ConnectedEntryCard = connect(
241
+ mapStateToProps,
242
+ mapDispatchToProps,
243
+ mergeProps,
244
+ )(translate()(EntryCard));
166
245
 
167
246
  export default ConnectedEntryCard;