mirror of
https://github.com/strapi/strapi.git
synced 2025-11-17 10:38:30 +00:00
Attributes list & delete attribute in GroupPage
This commit is contained in:
parent
d576b2129a
commit
c37f9e54df
@ -42,6 +42,18 @@ const List = styled.div`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
td {
|
||||||
|
padding: 0.75em;
|
||||||
|
vertical-align: middle;
|
||||||
|
font-size: 1.3rem;
|
||||||
|
line-height: 1.8rem;
|
||||||
|
&:first-of-type {
|
||||||
|
padding-left: calc(3rem + 0.75em);
|
||||||
|
}
|
||||||
|
&:last-of-type {
|
||||||
|
padding-right: calc(3rem + 0.75em);
|
||||||
|
}
|
||||||
|
}
|
||||||
tbody {
|
tbody {
|
||||||
color: ${colors.blueTxt};
|
color: ${colors.blueTxt};
|
||||||
tr {
|
tr {
|
||||||
@ -65,18 +77,6 @@ const List = styled.div`
|
|||||||
height: 0;
|
height: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
td {
|
|
||||||
padding: 0.75em;
|
|
||||||
vertical-align: middle;
|
|
||||||
font-size: 1.3rem;
|
|
||||||
line-height: 1.8rem;
|
|
||||||
&:first-of-type {
|
|
||||||
padding-left: calc(3rem + 0.75em);
|
|
||||||
}
|
|
||||||
&:last-of-type {
|
|
||||||
padding-right: calc(3rem + 0.75em);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@media (min-width: ${sizes.tablet}) {
|
@media (min-width: ${sizes.tablet}) {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@ -12,6 +12,12 @@ const ListWrapper = styled.div`
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
overflow-x: scroll;
|
overflow-x: scroll;
|
||||||
}
|
}
|
||||||
|
.list-button {
|
||||||
|
padding: 10px 30px 25px 30px;
|
||||||
|
button {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
@media (min-width: ${sizes.tablet}) {
|
@media (min-width: ${sizes.tablet}) {
|
||||||
.table-wrapper {
|
.table-wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* StyedListRow
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
const StyedListRow = styled.tr`
|
||||||
|
background-color: transparent;
|
||||||
|
cursor: pointer;
|
||||||
|
p {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
width: 35px;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
background-color: #f7f8f8;
|
||||||
|
}
|
||||||
|
td:first-of-type {
|
||||||
|
padding-left: 3rem;
|
||||||
|
}
|
||||||
|
td:nth-child(2) {
|
||||||
|
width: 25rem;
|
||||||
|
p {
|
||||||
|
font-weight: 500;
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
td:last-child {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default StyedListRow;
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
import boolean from '../../assets/images/icon_boolean.png';
|
||||||
|
import date from '../../assets/images/icon_date.png';
|
||||||
|
import email from '../../assets/images/icon_email.png';
|
||||||
|
import enumeration from '../../assets/images/icon_enumeration.png';
|
||||||
|
import media from '../../assets/images/icon_media.png';
|
||||||
|
import json from '../../assets/images/icon_json.png';
|
||||||
|
import number from '../../assets/images/icon_number.png';
|
||||||
|
import password from '../../assets/images/icon_password.png';
|
||||||
|
import relation from '../../assets/images/icon_relation.png';
|
||||||
|
import string from '../../assets/images/icon_string.png';
|
||||||
|
import text from '../../assets/images/icon_text.png';
|
||||||
|
|
||||||
|
const assets = {
|
||||||
|
boolean,
|
||||||
|
date,
|
||||||
|
email,
|
||||||
|
enumeration,
|
||||||
|
media,
|
||||||
|
json,
|
||||||
|
number,
|
||||||
|
password,
|
||||||
|
relation,
|
||||||
|
string,
|
||||||
|
text,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default assets;
|
||||||
@ -0,0 +1,146 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
|
import { PopUpWarning } from 'strapi-helper-plugin';
|
||||||
|
import pluginId from '../../pluginId';
|
||||||
|
|
||||||
|
import StyledListRow from './StyledListRow';
|
||||||
|
|
||||||
|
import assets from './assets';
|
||||||
|
|
||||||
|
function ListRow({
|
||||||
|
canOpenModal,
|
||||||
|
deleteAttribute,
|
||||||
|
isTemporary,
|
||||||
|
name,
|
||||||
|
onClickGoTo,
|
||||||
|
source,
|
||||||
|
uid,
|
||||||
|
target,
|
||||||
|
type,
|
||||||
|
}) {
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
|
const ico = ['integer', 'biginteger', 'float', 'decimal'].includes(type)
|
||||||
|
? 'number'
|
||||||
|
: type;
|
||||||
|
|
||||||
|
const src = target ? assets.relation : assets[ico];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<StyledListRow
|
||||||
|
onClick={e => {
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
const to = uid || name;
|
||||||
|
onClickGoTo(to, source);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<td>
|
||||||
|
<img src={src} alt={`icon-${ico}`} />
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p>
|
||||||
|
{name}
|
||||||
|
{source && (
|
||||||
|
<FormattedMessage id={`${pluginId}.from`}>
|
||||||
|
{message => (
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
fontStyle: 'italic',
|
||||||
|
color: '#787E8F',
|
||||||
|
fontWeight: '500',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
({message}: {source})
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</FormattedMessage>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{isTemporary && (
|
||||||
|
<FormattedMessage
|
||||||
|
id={`${pluginId}.contentType.temporaryDisplay`}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<FormattedMessage id={`${pluginId}.attribute.${type}`} />
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{!source && (
|
||||||
|
<>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={e => {
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
const to = uid || name;
|
||||||
|
onClickGoTo(to, source, canOpenModal || isTemporary);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<i className="fa fa-pencil link-icon" />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={e => {
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
if (canOpenModal || isTemporary) {
|
||||||
|
setIsOpen(true);
|
||||||
|
} else {
|
||||||
|
strapi.notification.info(
|
||||||
|
`${pluginId}.notification.info.work.notSaved`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<i className="fa fa-trash link-icon" />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<PopUpWarning
|
||||||
|
isOpen={isOpen}
|
||||||
|
toggleModal={() => setIsOpen(prevState => !prevState)}
|
||||||
|
content={{
|
||||||
|
message: `${pluginId}.popUpWarning.bodyMessage.${
|
||||||
|
type === 'models' ? 'contentType' : 'groups'
|
||||||
|
}.delete`,
|
||||||
|
}}
|
||||||
|
type="danger"
|
||||||
|
onConfirm={() => {
|
||||||
|
setIsOpen(false);
|
||||||
|
deleteAttribute(name);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
</StyledListRow>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ListRow.defaultProps = {
|
||||||
|
target: null,
|
||||||
|
source: null,
|
||||||
|
uid: null,
|
||||||
|
deleteAttribute: () => {},
|
||||||
|
};
|
||||||
|
|
||||||
|
ListRow.propTypes = {
|
||||||
|
canOpenModal: PropTypes.bool,
|
||||||
|
context: PropTypes.object,
|
||||||
|
deleteAttribute: PropTypes.func,
|
||||||
|
isTemporary: PropTypes.bool.isRequired,
|
||||||
|
name: PropTypes.string.isRequired,
|
||||||
|
onClickGoTo: PropTypes.func.isRequired,
|
||||||
|
source: PropTypes.string,
|
||||||
|
uid: PropTypes.string,
|
||||||
|
type: PropTypes.string.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ListRow;
|
||||||
@ -15,6 +15,7 @@ import {
|
|||||||
CREATE_TEMP_CONTENT_TYPE,
|
CREATE_TEMP_CONTENT_TYPE,
|
||||||
CREATE_TEMP_GROUP,
|
CREATE_TEMP_GROUP,
|
||||||
DELETE_GROUP,
|
DELETE_GROUP,
|
||||||
|
DELETE_GROUP_ATTRIBUTE,
|
||||||
DELETE_GROUP_SUCCEEDED,
|
DELETE_GROUP_SUCCEEDED,
|
||||||
DELETE_MODEL,
|
DELETE_MODEL,
|
||||||
DELETE_MODEL_ATTRIBUTE,
|
DELETE_MODEL_ATTRIBUTE,
|
||||||
@ -113,6 +114,13 @@ export function deleteGroup(uid) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function deleteGroupAttribute(keys) {
|
||||||
|
return {
|
||||||
|
type: DELETE_GROUP_ATTRIBUTE,
|
||||||
|
keys,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function deleteGroupSucceeded(uid) {
|
export function deleteGroupSucceeded(uid) {
|
||||||
return {
|
return {
|
||||||
type: DELETE_GROUP_SUCCEEDED,
|
type: DELETE_GROUP_SUCCEEDED,
|
||||||
|
|||||||
@ -20,6 +20,8 @@ export const CREATE_TEMP_CONTENT_TYPE =
|
|||||||
'ContentTypeBuilder/App/CREATE_TEMP_CONTENT_TYPE';
|
'ContentTypeBuilder/App/CREATE_TEMP_CONTENT_TYPE';
|
||||||
export const CREATE_TEMP_GROUP = 'ContentTypeBuilder/App/CREATE_TEMP_GROUP';
|
export const CREATE_TEMP_GROUP = 'ContentTypeBuilder/App/CREATE_TEMP_GROUP';
|
||||||
export const DELETE_GROUP = 'ContentTypeBuilder/App/DELETE_GROUP';
|
export const DELETE_GROUP = 'ContentTypeBuilder/App/DELETE_GROUP';
|
||||||
|
export const DELETE_GROUP_ATTRIBUTE =
|
||||||
|
'ContentTypeBuilder/App/DELETE_GROUP_ATTRIBUTE';
|
||||||
export const DELETE_GROUP_SUCCEEDED =
|
export const DELETE_GROUP_SUCCEEDED =
|
||||||
'ContentTypeBuilder/App/DELETE_GROUP_SUCCEEDED';
|
'ContentTypeBuilder/App/DELETE_GROUP_SUCCEEDED';
|
||||||
export const DELETE_MODEL = 'ContentTypeBuilder/App/DELETE_MODEL';
|
export const DELETE_MODEL = 'ContentTypeBuilder/App/DELETE_MODEL';
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import {
|
|||||||
CLEAR_TEMPORARY_ATTRIBUTE_RELATION,
|
CLEAR_TEMPORARY_ATTRIBUTE_RELATION,
|
||||||
CREATE_TEMP_CONTENT_TYPE,
|
CREATE_TEMP_CONTENT_TYPE,
|
||||||
CREATE_TEMP_GROUP,
|
CREATE_TEMP_GROUP,
|
||||||
|
DELETE_GROUP_ATTRIBUTE,
|
||||||
DELETE_GROUP_SUCCEEDED,
|
DELETE_GROUP_SUCCEEDED,
|
||||||
DELETE_MODEL_ATTRIBUTE,
|
DELETE_MODEL_ATTRIBUTE,
|
||||||
DELETE_MODEL_SUCCEEDED,
|
DELETE_MODEL_SUCCEEDED,
|
||||||
@ -258,6 +259,20 @@ function appReducer(state = initialState, action) {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
.update('newGroupClone', () => state.get('newGroup'));
|
.update('newGroupClone', () => state.get('newGroup'));
|
||||||
|
case DELETE_GROUP_ATTRIBUTE: {
|
||||||
|
const pathToAttributes = action.keys
|
||||||
|
.slice()
|
||||||
|
.reverse()
|
||||||
|
.splice(1)
|
||||||
|
.reverse();
|
||||||
|
const attributes = state.getIn(pathToAttributes);
|
||||||
|
const attributeName = action.keys.pop();
|
||||||
|
const attributeToDelete = attributes.findIndex(
|
||||||
|
attribute => attribute.get('name') === attributeName
|
||||||
|
);
|
||||||
|
|
||||||
|
return state.removeIn([...pathToAttributes, attributeToDelete]);
|
||||||
|
}
|
||||||
case DELETE_GROUP_SUCCEEDED:
|
case DELETE_GROUP_SUCCEEDED:
|
||||||
console.log({
|
console.log({
|
||||||
st: state
|
st: state
|
||||||
|
|||||||
@ -1,22 +1,49 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { get } from 'lodash';
|
import { connect } from 'react-redux';
|
||||||
|
import { bindActionCreators, compose } from 'redux';
|
||||||
|
import { get, pickBy } from 'lodash';
|
||||||
|
|
||||||
import pluginId from '../../pluginId';
|
import pluginId from '../../pluginId';
|
||||||
|
|
||||||
import ViewContainer from '../ViewContainer';
|
import ViewContainer from '../ViewContainer';
|
||||||
import AttributesModalPicker from '../AttributesPickerModal';
|
import AttributesModalPicker from '../AttributesPickerModal';
|
||||||
|
|
||||||
|
import ListRow from '../../components/ListRow';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
BackHeader,
|
BackHeader,
|
||||||
|
Button,
|
||||||
EmptyAttributesBlock,
|
EmptyAttributesBlock,
|
||||||
getQueryParameters,
|
getQueryParameters,
|
||||||
|
ListWrapper,
|
||||||
|
ListHeader,
|
||||||
|
List,
|
||||||
} from 'strapi-helper-plugin';
|
} from 'strapi-helper-plugin';
|
||||||
|
|
||||||
|
import { deleteGroupAttribute } from '../App/actions';
|
||||||
|
|
||||||
/* eslint-disable no-extra-boolean-cast */
|
/* eslint-disable no-extra-boolean-cast */
|
||||||
class GroupPage extends React.Component {
|
export class GroupPage extends React.Component {
|
||||||
featureType = 'group';
|
featureType = 'group';
|
||||||
|
|
||||||
|
getFeature = () => {
|
||||||
|
const { modifiedDataGroup, newGroup } = this.props;
|
||||||
|
|
||||||
|
if (this.isUpdatingTempFeature()) {
|
||||||
|
return newGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
return get(modifiedDataGroup, this.getFeatureName(), {});
|
||||||
|
};
|
||||||
|
|
||||||
|
getFeatureSchema = () => get(this.getFeature(), 'schema', {});
|
||||||
|
|
||||||
|
getFeatureAttributes = () => get(this.getFeatureSchema(), 'attributes', []);
|
||||||
|
|
||||||
|
getFeatureAttributesLength = () =>
|
||||||
|
Object.keys(this.getFeatureAttributes()).length;
|
||||||
|
|
||||||
getFeatureName = () => {
|
getFeatureName = () => {
|
||||||
const {
|
const {
|
||||||
match: {
|
match: {
|
||||||
@ -66,6 +93,21 @@ class GroupPage extends React.Component {
|
|||||||
return search;
|
return search;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
handleDeleteGroupAttribute = attrToDelete => {
|
||||||
|
const { deleteGroupAttribute } = this.props;
|
||||||
|
|
||||||
|
const keys = this.isUpdatingTempFeature()
|
||||||
|
? ['newGroup', 'schema', 'attributes', attrToDelete]
|
||||||
|
: [
|
||||||
|
'modifiedDataGroup',
|
||||||
|
this.getFeatureName(),
|
||||||
|
'schema',
|
||||||
|
'attributes',
|
||||||
|
attrToDelete,
|
||||||
|
];
|
||||||
|
deleteGroupAttribute(keys);
|
||||||
|
};
|
||||||
|
|
||||||
handleGoBack = () => this.props.history.goBack();
|
handleGoBack = () => this.props.history.goBack();
|
||||||
|
|
||||||
isUpdatingTempFeature = () => {
|
isUpdatingTempFeature = () => {
|
||||||
@ -77,9 +119,22 @@ class GroupPage extends React.Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
|
canOpenModal,
|
||||||
history: { push },
|
history: { push },
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
|
const attributes = this.getFeatureAttributes();
|
||||||
|
const attributesNumber = this.getFeatureAttributesLength();
|
||||||
|
let listTitle = `${pluginId}.table.attributes.title.${
|
||||||
|
attributesNumber > 1 ? 'plural' : 'singular'
|
||||||
|
}`;
|
||||||
|
|
||||||
|
const buttonProps = {
|
||||||
|
kind: 'secondaryHotlineAdd',
|
||||||
|
label: `${pluginId}.button.attributes.add`,
|
||||||
|
onClick: this.handleClick,
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<BackHeader onClick={this.handleGoBack} />
|
<BackHeader onClick={this.handleGoBack} />
|
||||||
@ -89,14 +144,47 @@ class GroupPage extends React.Component {
|
|||||||
headerTitle={this.getFeatureHeaderTitle()}
|
headerTitle={this.getFeatureHeaderTitle()}
|
||||||
headerDescription={this.getFeatureHeaderDescription()}
|
headerDescription={this.getFeatureHeaderDescription()}
|
||||||
>
|
>
|
||||||
<EmptyAttributesBlock
|
{attributesNumber === 0 ? (
|
||||||
description={`${pluginId}.home.emptyAttributes.description.${
|
<EmptyAttributesBlock
|
||||||
this.featureType
|
description={`${pluginId}.home.emptyAttributes.description.${
|
||||||
}`}
|
this.featureType
|
||||||
id="openAddAttr"
|
}`}
|
||||||
label="content-type-builder.button.attributes.add"
|
id="openAddAttr"
|
||||||
title="content-type-builder.home.emptyAttributes.title"
|
label="content-type-builder.button.attributes.add"
|
||||||
/>
|
title="content-type-builder.home.emptyAttributes.title"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<ListWrapper>
|
||||||
|
<ListHeader
|
||||||
|
title={listTitle}
|
||||||
|
titleValues={{ number: attributesNumber }}
|
||||||
|
relationTitle={listTitle}
|
||||||
|
relationTitleValues={{ number: attributesNumber }}
|
||||||
|
button={{ ...buttonProps }}
|
||||||
|
/>
|
||||||
|
<List>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
{attributes.map(attribute => (
|
||||||
|
<ListRow
|
||||||
|
key={attribute.name}
|
||||||
|
canOpenModal={canOpenModal}
|
||||||
|
context={this.context}
|
||||||
|
deleteAttribute={this.handleDeleteGroupAttribute}
|
||||||
|
{...attribute}
|
||||||
|
type={attribute.type}
|
||||||
|
isTemporary={false}
|
||||||
|
onClickGoTo={() => {}}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</List>
|
||||||
|
<div className="list-button">
|
||||||
|
<Button {...buttonProps} />
|
||||||
|
</div>
|
||||||
|
</ListWrapper>
|
||||||
|
)}
|
||||||
</ViewContainer>
|
</ViewContainer>
|
||||||
<AttributesModalPicker
|
<AttributesModalPicker
|
||||||
isOpen={this.getModalType() === 'chooseAttributes'}
|
isOpen={this.getModalType() === 'chooseAttributes'}
|
||||||
@ -108,6 +196,7 @@ class GroupPage extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GroupPage.propTypes = {
|
GroupPage.propTypes = {
|
||||||
|
deleteGroupAttribute: PropTypes.func.isRequired,
|
||||||
groups: PropTypes.array.isRequired,
|
groups: PropTypes.array.isRequired,
|
||||||
history: PropTypes.shape({
|
history: PropTypes.shape({
|
||||||
push: PropTypes.func.isRequired,
|
push: PropTypes.func.isRequired,
|
||||||
@ -124,4 +213,18 @@ GroupPage.propTypes = {
|
|||||||
newGroup: PropTypes.object.isRequired,
|
newGroup: PropTypes.object.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default GroupPage;
|
export function mapDispatchToProps(dispatch) {
|
||||||
|
return bindActionCreators(
|
||||||
|
{
|
||||||
|
deleteGroupAttribute,
|
||||||
|
},
|
||||||
|
dispatch
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const withConnect = connect(
|
||||||
|
null,
|
||||||
|
mapDispatchToProps
|
||||||
|
);
|
||||||
|
|
||||||
|
export default compose(withConnect)(GroupPage);
|
||||||
|
|||||||
@ -1,10 +1,14 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from 'enzyme';
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
import GroupPage from '../index';
|
import { EmptyAttributesBlock } from 'strapi-helper-plugin';
|
||||||
|
import { GroupPage, mapDispatchToProps } from '../index';
|
||||||
|
|
||||||
|
import { deleteGroupAttribute } from '../../App/actions';
|
||||||
|
|
||||||
const basePath = '/plugins/content-type-builder/groups';
|
const basePath = '/plugins/content-type-builder/groups';
|
||||||
const props = {
|
const props = {
|
||||||
|
deleteGroupAttribute: jest.fn(),
|
||||||
groups: [
|
groups: [
|
||||||
{
|
{
|
||||||
icon: 'fa-cube',
|
icon: 'fa-cube',
|
||||||
@ -89,6 +93,17 @@ describe('CTB <GroupPage />', () => {
|
|||||||
shallow(<GroupPage {...props} />);
|
shallow(<GroupPage {...props} />);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('CTB <ModelPage /> render', () => {
|
||||||
|
it("should display the EmptyAttributeBlock if the group's attributes are empty", () => {
|
||||||
|
props.initialDataGroup.tests.schema.attributes = {};
|
||||||
|
props.modifiedDataGroup.tests.schema.attributes = {};
|
||||||
|
|
||||||
|
const wrapper = shallow(<GroupPage {...props} />);
|
||||||
|
|
||||||
|
expect(wrapper.find(EmptyAttributesBlock)).toHaveLength(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('GetFeatureHeaderDescription', () => {
|
describe('GetFeatureHeaderDescription', () => {
|
||||||
it("should return the model's description field", () => {
|
it("should return the model's description field", () => {
|
||||||
const { getFeatureHeaderDescription } = shallow(
|
const { getFeatureHeaderDescription } = shallow(
|
||||||
@ -99,7 +114,22 @@ describe('CTB <GroupPage />', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getFeatureName', () => {
|
describe('GetFeature', () => {
|
||||||
|
it('should return the correct model', () => {
|
||||||
|
const { getFeature } = shallow(<GroupPage {...props} />).instance();
|
||||||
|
|
||||||
|
expect(getFeature()).toEqual(props.modifiedDataGroup.tests);
|
||||||
|
});
|
||||||
|
it('should return newGroup isTemporary is true', () => {
|
||||||
|
props.groups.find(item => item.name == 'tests').isTemporary = true;
|
||||||
|
|
||||||
|
const { getFeature } = shallow(<GroupPage {...props} />).instance();
|
||||||
|
|
||||||
|
expect(getFeature()).toEqual(props.newGroup);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('GetFeatureName', () => {
|
||||||
it("should return the model's name field", () => {
|
it("should return the model's name field", () => {
|
||||||
const { getFeatureName } = shallow(<GroupPage {...props} />).instance();
|
const { getFeatureName } = shallow(<GroupPage {...props} />).instance();
|
||||||
|
|
||||||
@ -107,3 +137,37 @@ describe('CTB <GroupPage />', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('CTB <GroupPage />, mapDispatchToProps', () => {
|
||||||
|
describe('DeleteGroupAttribute', () => {
|
||||||
|
it('should be injected', () => {
|
||||||
|
const dispatch = jest.fn();
|
||||||
|
const result = mapDispatchToProps(dispatch);
|
||||||
|
|
||||||
|
expect(result.deleteGroupAttribute).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call deleteGroupAttribute with modifiedDataGroup path when isTemporary is false', () => {
|
||||||
|
props.groups.find(item => item.name == 'tests').isTemporary = false;
|
||||||
|
|
||||||
|
const { handleDeleteGroupAttribute } = shallow(
|
||||||
|
<GroupPage {...props} />
|
||||||
|
).instance();
|
||||||
|
handleDeleteGroupAttribute('name');
|
||||||
|
|
||||||
|
const keys = ['modifiedDataGroup', 'tests', 'schema', 'attributes', 'name'];
|
||||||
|
expect(props.deleteGroupAttribute).toHaveBeenCalledWith(keys);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call deleteGroupAttribute with modifiedDataGroup path when isTemporary is true', () => {
|
||||||
|
props.groups.find(item => item.name == 'tests').isTemporary = true;
|
||||||
|
const { handleDeleteGroupAttribute } = shallow(
|
||||||
|
<GroupPage {...props} />
|
||||||
|
).instance();
|
||||||
|
|
||||||
|
handleDeleteGroupAttribute('name');
|
||||||
|
const keys = ['newGroup', 'schema', 'attributes', 'name'];
|
||||||
|
expect(props.deleteGroupAttribute).toHaveBeenCalledWith(keys);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@ -191,5 +191,7 @@
|
|||||||
"table.contentType.title.singular": "{number} Content Type is available",
|
"table.contentType.title.singular": "{number} Content Type is available",
|
||||||
"table.groups.title.plural": "{number} Groups are available",
|
"table.groups.title.plural": "{number} Groups are available",
|
||||||
"table.groups.title.singular": "{number} Group is available",
|
"table.groups.title.singular": "{number} Group is available",
|
||||||
|
"table.attributes.title.plural": "{number} fields",
|
||||||
|
"table.attributes.title.singular": "{number} field",
|
||||||
"prompt.content.unsaved": "Are you sure you want to leave this content type? All your modifications will be lost."
|
"prompt.content.unsaved": "Are you sure you want to leave this content type? All your modifications will be lost."
|
||||||
}
|
}
|
||||||
|
|||||||
@ -185,5 +185,7 @@
|
|||||||
"table.contentType.title.singular": "{number} Type de Contenu est disponible",
|
"table.contentType.title.singular": "{number} Type de Contenu est disponible",
|
||||||
"table.group.title.plural": "{number} Groupes sont disponibles",
|
"table.group.title.plural": "{number} Groupes sont disponibles",
|
||||||
"table.group.title.singular": "{number} Groupe est disponible",
|
"table.group.title.singular": "{number} Groupe est disponible",
|
||||||
|
"table.attributes.title.plural": "{number} chammps",
|
||||||
|
"table.attributes.title.singular": "{number} champ",
|
||||||
"prompt.content.unsaved": "Etes-vous sûr de vouloir quitter ce model? Toutes vos modifications seront perdues."
|
"prompt.content.unsaved": "Etes-vous sûr de vouloir quitter ce model? Toutes vos modifications seront perdues."
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,6 +25,7 @@ module.exports = {
|
|||||||
model: 'file',
|
model: 'file',
|
||||||
via: 'related',
|
via: 'related',
|
||||||
plugin: 'upload',
|
plugin: 'upload',
|
||||||
|
type: 'media',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -50,6 +51,23 @@ module.exports = {
|
|||||||
model: 'file',
|
model: 'file',
|
||||||
via: 'related',
|
via: 'related',
|
||||||
plugin: 'upload',
|
plugin: 'upload',
|
||||||
|
type: 'media',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uid: 'cats',
|
||||||
|
name: 'Cats',
|
||||||
|
source: null,
|
||||||
|
schema: {
|
||||||
|
connection: 'default',
|
||||||
|
collectionName: 'cats',
|
||||||
|
description: 'Little description for cats group',
|
||||||
|
attributes: {
|
||||||
|
name: {
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -62,12 +80,7 @@ module.exports = {
|
|||||||
connection: 'default',
|
connection: 'default',
|
||||||
collectionName: 'cars',
|
collectionName: 'cars',
|
||||||
description: 'Little description for cars group',
|
description: 'Little description for cars group',
|
||||||
attributes: {
|
attributes: {},
|
||||||
name: {
|
|
||||||
type: 'string',
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
//...
|
//...
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user