Skip to content

Commit

Permalink
Merge pull request #45 from VirtusLab/fix/draft-and-publish-flow-covered
Browse files Browse the repository at this point in the history
fix: providing coverage for draft and publish Strapi content types
  • Loading branch information
cyp3rius authored Mar 8, 2021
2 parents 9227c04 + e31b19e commit c695af8
Show file tree
Hide file tree
Showing 22 changed files with 356 additions and 166 deletions.
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ Complete installation requirements are exact same as for Strapi itself and can b

**Supported Strapi versions**:

- Strapi v3.5.0 (recently tested)
- Strapi v3.5.2 (recently tested)
- Strapi v3.x

(This plugin may work with the older Strapi versions, but these are not tested nor officially supported at this time.)
Expand Down Expand Up @@ -109,7 +109,6 @@ To setup the plugin properly we recommend to put following snippet as part of `c
plugins: {
navigation: {
additionalFields: ['audience'],
excludedContentTypes: ["plugins::", "strapi"],
allowedLevels: 2,
contentTypesNameFields: {
'blog_posts': ['altTitle'],
Expand All @@ -122,7 +121,6 @@ To setup the plugin properly we recommend to put following snippet as part of `c

### Properties
- `additionalFields` - Additional fields: 'audience', more in the future
- `excludedContentTypes` - Excluded content types patterns (by default built-in and plugin specific content types)
- `allowedLevels` - Maximum level for which your're able to mark item as "Menu attached"
- `contentTypesNameFields` - Definition of content type title fields like `'content_type_name': ['field_name_1', 'field_name_2']`, if not set titles are pulled from fields like `['title', 'subject', 'name']`

Expand Down Expand Up @@ -369,7 +367,17 @@ If you would like to use the [Strapi Molecules Audit Log](https://github.com/Vir
```
As a last step you've to provide the Navigation class to let Audit Log use it. To not provide external & hard dependencies we've added the example of class code in the `examples/audit-log-integration.js` .

## Examples

Live example of plugin usage can be found in the [VirtusLab Strapi Examples](https://github.com/VirtusLab/strapi-examples/tree/master/strapi-plugin-navigation) repository.

## Q&A

### Content Types

**Q:** I've recognized **Navigation Item** and **Navigation** collection types in the Collections sidebar section, but they are not working properly. What should I do?

**A:** As an authors of the plugin we're not supporting any editing of mentioned content types via built-in Strapi Content Manager. Plugin delivers highly customized & extended functionality which might be covered only by dedicated editor UI accessible via **Plugins Section > UI Navigation**. Only issues that has been recognized there, are in the scope of support we've providing.

## Contributing

Expand Down
2 changes: 1 addition & 1 deletion __mocks__/helpers/pages.settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"kind": "collectionType",
"collectionName": "pages",
"info": {
"name": "pages"
"name": "Pages"
},
"options": {
"increments": true,
Expand Down
12 changes: 8 additions & 4 deletions admin/src/components/Item/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import CardItemLevelAdd from './CardItemLevelAdd';
import List from '../List';
import CardItemLevelWrapper from './CardItemLevelWrapper';
import CardItemRestore from './CardItemRestore';
import pluginId from '../../pluginId';
import ItemOrdering from '../ItemOrdering';
import { getTrad } from '../../translations';

const Item = (props) => {
const {
Expand All @@ -25,6 +25,7 @@ const Item = (props) => {
levelPath = '',
allowedLevels,
contentTypesNameFields,
contentTypes,
relatedRef,
isFirst = false,
isLast = false,
Expand All @@ -40,15 +41,18 @@ const Item = (props) => {
title,
type,
path,
relatedType,
removed,
externalPath,
menuAttached,
} = item;
const footerProps = {
contentTypes,
type: type || navigationItemType.INTERNAL,
removed,
menuAttached,
relatedRef,
relatedType,
contentTypesNameFields,
attachButtons: !(isFirst && isLast),
};
Expand Down Expand Up @@ -88,9 +92,7 @@ const Item = (props) => {
<Button
onClick={e => onItemRestoreClick(e, item)}
color="secondary"
label={formatMessage({
id: `${pluginId}.popup.item.form.button.restore`,
})}
label={formatMessage(getTrad('popup.item.form.button.restore'))}
/>
</CardItemRestore>)}
<CardItemTitle>{title}</CardItemTitle>
Expand Down Expand Up @@ -125,6 +127,7 @@ const Item = (props) => {
allowedLevels={allowedLevels}
isParentAttachedToMenu={menuAttached}
contentTypesNameFields={contentTypesNameFields}
contentTypes={contentTypes}
error={error}
/>
)}
Expand All @@ -144,6 +147,7 @@ Item.propTypes = {
menuAttached: PropTypes.bool,
}).isRequired,
relatedRef: PropTypes.object,
contentTypes: PropTypes.array,
contentTypesNameFields: PropTypes.object.isRequired,
level: PropTypes.number,
levelPath: PropTypes.string,
Expand Down
11 changes: 11 additions & 0 deletions admin/src/components/ItemFooter/CardItemError.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import styled from "styled-components";

import { sizes } from "strapi-helper-plugin";
import CardItemRelation from "./CardItemRelation";

const CardItemError = styled(CardItemRelation)`
color: red;
font-weight: bold;
`;

export default CardItemError;
17 changes: 17 additions & 0 deletions admin/src/components/ItemFooter/CardItemRelationStatus.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import styled from "styled-components";

import { colors, sizes } from "strapi-helper-plugin";

const CardItemRelationStatus = styled.small`
display: inline-block;
padding: ${`${sizes.margin * .1}px ${sizes.margin * .5}px`};
margin-left: ${`${sizes.margin / 2}px`};
color: #ffffff;
font-weight: bold;
background: orange;
border-radius: ${`${sizes.margin * .3}px`};
`;

export default CardItemRelationStatus;
35 changes: 28 additions & 7 deletions admin/src/components/ItemFooter/index.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,32 @@
import React from 'react';
import { useIntl } from 'react-intl';
import PropTypes from 'prop-types';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faLink, faGlobe, faSitemap } from '@fortawesome/free-solid-svg-icons';
import { faLink, faGlobe, faSitemap, faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
import CardItemRelation from './CardItemRelation';
import CardItemType from './CardItemType';
import Wrapper from './Wrapper';
import { isNil, get, upperFirst } from 'lodash';
import { isNil, get, find, upperFirst } from 'lodash';
import { navigationItemType } from '../../containers/View/utils/enums';
import { extractRelatedItemLabel } from '../../containers/View/utils/parsers';
import { extractRelatedItemLabel, isRelationCorrect, isRelationPublished } from '../../containers/View/utils/parsers';
import CardItemError from './CardItemError';
import CardItemRelationStatus from './CardItemRelationStatus';
import { getTrad } from '../../translations';

const ItemFooter = ({ type, removed, relatedRef, relatedType, attachButtons, contentTypesNameFields, contentTypes }) => {
const { formatMessage } = useIntl();

const isRelationDefined = !isNil(relatedRef);

const ItemFooter = ({ type, removed, relatedRef, attachButtons, contentTypesNameFields }) => {
const formatRelationType = () =>
!isNil(relatedRef) ? get(relatedRef, 'labelSingular', get(relatedRef, '__contentType')) : '';
isRelationDefined ? get(relatedRef, 'labelSingular', get(relatedRef, '__contentType')) : '';

const formatRelationName = () =>
!isNil(relatedRef) ? extractRelatedItemLabel(relatedRef, contentTypesNameFields) : '';
isRelationDefined ? extractRelatedItemLabel(relatedRef, contentTypesNameFields) : '';

const isSingle = get(relatedRef, 'isSingle', false);
const isExternal = type === navigationItemType.EXTERNAL;
const relatedContentType = isRelationDefined && isSingle ? find(contentTypes, cnt => cnt.uid === relatedType) : undefined;

return (
<Wrapper removed={removed} attachButtons={attachButtons}>
Expand All @@ -26,12 +36,23 @@ const ItemFooter = ({ type, removed, relatedRef, attachButtons, contentTypesName
/>{' '}
{upperFirst(type.toLowerCase())}
</CardItemType>
{!isNil(relatedRef) && (
{isRelationCorrect({ type, related: relatedRef }) && !isExternal && (
<CardItemRelation title={formatRelationName()}>
<FontAwesomeIcon icon={faLink} />{' '}
{isSingle ? formatRelationType() : `(${formatRelationType()}) ${formatRelationName()}`}
{ !isRelationPublished({ relatedRef, relatedType: relatedContentType, type, isCollection: !isNil(relatedContentType) }) && (
<CardItemRelationStatus>
{ `${formatMessage(getTrad('notification.navigation.item.relation.status.draft'))}` }
</CardItemRelationStatus>
) }
</CardItemRelation>
)}
{ !isRelationCorrect({ type, related: relatedRef }) && (
<CardItemError title={formatRelationName()}>
<FontAwesomeIcon icon={faExclamationTriangle} />{' '}
{ formatMessage(getTrad('notification.navigation.item.relation')) }
</CardItemError>
)}
</Wrapper>
);
};
Expand Down
3 changes: 3 additions & 0 deletions admin/src/components/List/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const List = ({
levelPath = '',
allowedLevels,
isParentAttachedToMenu = false,
contentTypes,
contentTypesNameFields,
error,
}) => {
Expand All @@ -43,6 +44,7 @@ const List = ({
onItemReOrder={onItemReOrder}
onItemRestoreClick={onItemRestoreClick}
onItemLevelAddClick={onItemLevelAddClick}
contentTypes={contentTypes}
error={error}
/>
);
Expand All @@ -68,6 +70,7 @@ List.propTypes = {
level: PropTypes.number,
allowedLevels: PropTypes.number,
isParentAttachedToMenu: PropTypes.bool,
contentTypes: PropTypes.array,
contentTypesNameFields: PropTypes.object.isRequired,
onItemClick: PropTypes.func.isRequired,
onItemReOrder: PropTypes.func.isRequired,
Expand Down
12 changes: 8 additions & 4 deletions admin/src/containers/DataManagerProvider/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
SUBMIT_NAVIGATION_ERROR,
} from './actions';
import { prepareItemToViewPayload } from '../View/utils/parsers';
import { getTradId } from "../../translations";

const DataManagerProvider = ({ children }) => {
const [reducerState, dispatch] = useReducer(reducer, initialState, init);
Expand Down Expand Up @@ -165,7 +166,7 @@ const DataManagerProvider = ({ children }) => {
type: GET_CONTENT_TYPE_ITEMS,
});
const url = plugin ? `/${plugin}/${type}` : `/${type}`;
const contentTypeItems = await request(url, {
const contentTypeItems = await request(`${url}?_publicationState=preview`, {
method: "GET",
signal,
});
Expand Down Expand Up @@ -239,11 +240,14 @@ const DataManagerProvider = ({ children }) => {

dispatch({
type: SUBMIT_NAVIGATION_SUCCEEDED,
navigation,
navigation: {
...navigation,
items: prepareItemToViewPayload(navigation.items, null, config),
},
});
emitEvent("didSubmitNavigation");

strapi.notification.success(`${pluginId}.notification.navigation.submit`);
strapi.notification.success(getTradId('notification.navigation.submit'));
} catch (err) {
dispatch({
type: SUBMIT_NAVIGATION_ERROR,
Expand All @@ -254,7 +258,7 @@ const DataManagerProvider = ({ children }) => {
if (err.response.payload.data && err.response.payload.data.errorTitles) {
return strapi.notification.error(
formatMessage(
{ id: `${pluginId}.notification.navigation.error` },
getTrad('notification.navigation.error'),
{ ...err.response.payload.data, errorTitles: err.response.payload.data.errorTitles.join(' and ') },
),
);
Expand Down
12 changes: 8 additions & 4 deletions admin/src/containers/DataManagerProvider/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,14 @@ const reducer = (state, action) => {
.update('error', () => undefined);
}
case SUBMIT_NAVIGATION_SUCCEEDED: {
return state.update(
'isLoadingForSubmit',
() => false,
);
const { navigation = {} } = action;
return state
.update("activeItem", () => fromJS(navigation))
.update("changedActiveItem", () => fromJS(navigation))
.update(
'isLoadingForSubmit',
() => false,
);
}
case SUBMIT_NAVIGATION_ERROR: {
return state
Expand Down
9 changes: 4 additions & 5 deletions admin/src/containers/DetailsView/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import CardWrapper from "../../components/ItemDetails/CardWrapper";
import CardLevelWrapper from "../../components/ItemDetails/CardLevelWrapper";
import EmptyView from "../../components/EmptyView";
import { isNil } from "lodash";
import { getTrad, getTradId } from "../../translations";

const DetailsView = () => {
const {
Expand Down Expand Up @@ -73,17 +74,15 @@ const DetailsView = () => {
<Wrapper className="col-md-8">
<Header
title={{
label: formatMessage({ id: `${pluginId}.moderation.header.title` }),
label: formatMessage(getTrad('moderation.header.title')),
}}
content={formatMessage({
id: `${pluginId}.moderation.header.description`,
})}
content={formatMessage(getTrad('moderation.header.description'))}
/>
{isLoadingForDetailsDataToBeSet && <LoadingIndicatorPage />}
{!isLoadingForDetailsDataToBeSet && !activeItem && (
<EmptyView fixPosition>
<FontAwesomeIcon icon={faComments} size="5x" />
<FormattedMessage id={`${pluginId}.moderation.content.empty`} />
<FormattedMessage id={getTradId('moderation.content.empty')} />
</EmptyView>
)}
{activeItem && (
Expand Down
8 changes: 4 additions & 4 deletions admin/src/containers/ListView/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import Wrapper from "../View/Wrapper";
import FadedWrapper from "../View/FadedWrapper";
import List from "../../components/List";
import EmptyView from "../../components/EmptyView";
import pluginId from "../../pluginId";
import { getTrad, getTradId } from "../../translations";

const ListView = () => {
const { items, isLoadingForDataToBeSet } = useDataManager();
Expand All @@ -29,10 +29,10 @@ const ListView = () => {
<Wrapper className="col-md-4">
<Header
title={{
label: formatMessage({ id: `${pluginId}.list.header.title` }),
label: formatMessage(getTrad('list.header.title')),
}}
content={formatMessage(
{ id: `${pluginId}.list.header.description` },
getTrad('list.header.description'),
{ count: newItemsCount },
)}
/>
Expand All @@ -41,7 +41,7 @@ const ListView = () => {
{isEmpty(items) && (
<EmptyView>
<FontAwesomeIcon icon={faSearch} size="5x" />
<FormattedMessage id={`${pluginId}.list.content.empty`} />
<FormattedMessage id={getTradId('list.content.empty')} />
</EmptyView>
)}
{!isEmpty(items) && <List items={[...items]} />}
Expand Down
Loading

0 comments on commit c695af8

Please sign in to comment.