feat(list): Add heading for list widgets (#5544)

This commit is contained in:
Sanjoth Rai 2021-07-14 20:13:50 +05:30 committed by GitHub
parent b94d5f6e7f
commit d60df8786d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 9 deletions

View File

@ -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)}

View File

@ -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', () => {