feat(list): Add heading for list widgets (#5544)
This commit is contained in:
parent
b94d5f6e7f
commit
d60df8786d
@ -4,11 +4,17 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import styled from '@emotion/styled';
|
||||
import { css, ClassNames } from '@emotion/core';
|
||||
import { List, Map, fromJS } from 'immutable';
|
||||
import { partial, isEmpty } from 'lodash';
|
||||
import { partial, isEmpty, uniqueId } from 'lodash';
|
||||
import uuid from 'uuid/v4';
|
||||
import { SortableContainer, SortableElement, SortableHandle } from 'react-sortable-hoc';
|
||||
import NetlifyCmsWidgetObject from 'netlify-cms-widget-object';
|
||||
import { ListItemTopBar, ObjectWidgetTopBar, colors, lengths } from 'netlify-cms-ui-default';
|
||||
import {
|
||||
ListItemTopBar,
|
||||
ObjectWidgetTopBar,
|
||||
colors,
|
||||
lengths,
|
||||
FieldLabel,
|
||||
} from 'netlify-cms-ui-default';
|
||||
import { stringTemplate, validations } from 'netlify-cms-lib-widgets';
|
||||
|
||||
import {
|
||||
@ -87,6 +93,14 @@ function validateItem(field, item) {
|
||||
|
||||
return true;
|
||||
}
|
||||
function LabelComponent({ field, isActive, hasErrors, uniqueFieldId, isFieldOptional, t }) {
|
||||
const label = `${field.get('label', field.get('name'))}`;
|
||||
return (
|
||||
<FieldLabel isActive={isActive} hasErrors={hasErrors} htmlFor={uniqueFieldId}>
|
||||
{label} {`${isFieldOptional ? ` (${t('editor.editorControl.field.optional')})` : ''}`}
|
||||
</FieldLabel>
|
||||
);
|
||||
}
|
||||
|
||||
export default class ListControl extends React.Component {
|
||||
validations = [];
|
||||
@ -164,6 +178,7 @@ export default class ListControl extends React.Component {
|
||||
}
|
||||
};
|
||||
|
||||
uniqueFieldId = uniqueId(`${this.props.field.get('name')}-field-`);
|
||||
/**
|
||||
* Always update so that each nested widget has the option to update. This is
|
||||
* required because ControlHOC provides a default `shouldComponentUpdate`
|
||||
@ -493,6 +508,7 @@ export default class ListControl extends React.Component {
|
||||
resolveWidget,
|
||||
parentIds,
|
||||
forID,
|
||||
t,
|
||||
} = this.props;
|
||||
|
||||
const { itemsCollapsed, keys } = this.state;
|
||||
@ -500,20 +516,29 @@ export default class ListControl extends React.Component {
|
||||
const key = keys[index];
|
||||
let field = this.props.field;
|
||||
const hasError = this.hasError(index);
|
||||
|
||||
if (this.getValueType() === valueTypes.MIXED) {
|
||||
const isVariableTypesList = this.getValueType() === valueTypes.MIXED;
|
||||
if (isVariableTypesList) {
|
||||
field = getTypedFieldForValue(field, item);
|
||||
if (!field) {
|
||||
return this.renderErroneousTypedItem(index, item);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<SortableListItem
|
||||
css={[styles.listControlItem, collapsed && styles.listControlItemCollapsed]}
|
||||
index={index}
|
||||
key={key}
|
||||
>
|
||||
{isVariableTypesList && (
|
||||
<LabelComponent
|
||||
field={field}
|
||||
isActive={false}
|
||||
hasErrors={hasError}
|
||||
uniqueFieldId={this.uniqueFieldId}
|
||||
isFieldOptional={field.get('required') === false}
|
||||
t={t}
|
||||
/>
|
||||
)}
|
||||
<StyledListItemTopBar
|
||||
collapsed={collapsed}
|
||||
onCollapseToggle={partial(this.handleItemCollapseToggle, index)}
|
||||
|
@ -299,14 +299,14 @@ describe('ListControl', () => {
|
||||
],
|
||||
});
|
||||
|
||||
const { getByText } = render(
|
||||
const { getAllByText } = render(
|
||||
<ListControl
|
||||
{...props}
|
||||
field={field}
|
||||
value={fromJS([{ first_name: 'hello', last_name: 'world', type: 'type_1_object' }])}
|
||||
/>,
|
||||
);
|
||||
expect(getByText('type_1_object')).toBeInTheDocument();
|
||||
expect(getAllByText('type_1_object')[1]).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should use label when no summary is configured for mixed types', () => {
|
||||
@ -327,14 +327,14 @@ describe('ListControl', () => {
|
||||
],
|
||||
});
|
||||
|
||||
const { getByText } = render(
|
||||
const { getAllByText } = render(
|
||||
<ListControl
|
||||
{...props}
|
||||
field={field}
|
||||
value={fromJS([{ first_name: 'hello', last_name: 'world', type: 'type_1_object' }])}
|
||||
/>,
|
||||
);
|
||||
expect(getByText('Type 1 Object')).toBeInTheDocument();
|
||||
expect(getAllByText('Type 1 Object')[1]).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should use summary when configured for mixed types', () => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user