Skip to content
This repository has been archived by the owner on Oct 1, 2024. It is now read-only.

chore(deps): update errata-ai/vale-action digest to 38bf078 - autoclosed #16

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/docslint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
uses: actions/checkout@v3

- name: Vale Linter
uses: errata-ai/vale-action@0dec3032fa59c4097deece7cf6ee3261b27bb3f1
uses: errata-ai/vale-action@38bf078c328061f59879b347ca344a718a736018
with:
# Optional
files: website/content/docs
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
dist/
*dist/
!packages/netlify-cms/dist
bin/
public/
node_modules/
Expand Down
10 changes: 5 additions & 5 deletions packages/netlify-cms-widget-code/src/CodeControl.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { ClassNames } from '@emotion/core';
import { Map } from 'immutable';
import { uniq, isEqual, isEmpty } from 'lodash';
import { uniq, isEqual, isEmpty, debounce } from 'lodash';
import uuid from 'uuid/v4';
import { UnControlled as ReactCodeMirror } from 'react-codemirror2';
import CodeMirror from 'codemirror';
Expand Down Expand Up @@ -99,6 +99,8 @@ export default class CodeControl extends React.Component {
this.updateCodeMirrorProps(prevState);
}

debounceOnChange = debounce(value => this.props.onChange(value), 300);

updateCodeMirrorProps(prevState) {
const keys = ['lang', 'theme', 'keyMap'];
const changedProps = getChangedProps(prevState, this.state, keys);
Expand Down Expand Up @@ -165,8 +167,6 @@ export default class CodeControl extends React.Component {
}

async handleChangeCodeMirrorProps(changedProps) {
const { onChange } = this.props;

if (changedProps.lang) {
const { mode } = this.getLanguageByName(changedProps.lang) || {};
if (mode) {
Expand Down Expand Up @@ -195,15 +195,15 @@ export default class CodeControl extends React.Component {
// Only persist the language change if supported - requires the value to be
// a map rather than just a code string.
if (changedProps.lang && this.valueIsMap()) {
onChange(this.toValue('lang', changedProps.lang));
this.debounceOnChange(this.toValue('lang', changedProps.lang));
}
}

handleChange(newValue) {
const cursor = this.cm.doc.getCursor();
const selections = this.cm.doc.listSelections();
this.setState({ lastKnownValue: newValue });
this.props.onChange(this.toValue('code', newValue), { cursor, selections });
this.debounceOnChange(this.toValue('code', newValue), { cursor, selections });
}

showSettings = () => {
Expand Down
35 changes: 27 additions & 8 deletions packages/netlify-cms-widget-colorstring/src/ColorControl.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import React from 'react';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import styled from '@emotion/styled';
import ChromePicker from 'react-color';
import validateColor from 'validate-color';
import { zIndex } from 'netlify-cms-ui-default';
import { debounce } from 'lodash';

function ClearIcon() {
return (
Expand Down Expand Up @@ -78,6 +80,7 @@ const ClickOutsideDiv = styled.div`

export default class ColorControl extends React.Component {
static propTypes = {
field: ImmutablePropTypes.map.isRequired,
onChange: PropTypes.func.isRequired,
forID: PropTypes.string,
value: PropTypes.node,
Expand All @@ -91,28 +94,44 @@ export default class ColorControl extends React.Component {
};

state = {
value: this.props.value,
showColorPicker: false,
};

debounceOnChange = debounce(value => this.props.onChange(value), 300);

// show/hide color picker
handleClick = () => {
this.setState({ showColorPicker: !this.state.showColorPicker });
};

handleClear = () => {
this.props.onChange('');
this.setState({ value: '' });
this.debounceOnChange('');
};

handleClose = () => {
this.setState({ showColorPicker: false });
};

handleInputChange = e => {
const { value } = e.target;
this.setState({ value });
this.debounceOnChange(value);
};

handleChange = color => {
const formattedColor =
color.rgb.a < 1
? `rgba(${color.rgb.r}, ${color.rgb.g}, ${color.rgb.b}, ${color.rgb.a})`
: color.hex;
this.props.onChange(formattedColor);
this.setState({ value: formattedColor });
this.debounceOnChange(formattedColor);
};

render() {
const { forID, value, field, onChange, classNameWrapper, setActiveStyle, setInactiveStyle } =
this.props;
const { forID, field, classNameWrapper, setActiveStyle, setInactiveStyle } = this.props;
const { value } = this.state;

const allowInput = field.get('allowInput', false);

Expand All @@ -123,7 +142,7 @@ export default class ColorControl extends React.Component {
<>
{' '}
{showClearButton && (
<ClearButtonWrapper>
<ClearButtonWrapper data-testid="clear-btn-wrapper">
<ClearButton onClick={this.handleClear}>
<ClearIcon />
</ClearButton>
Expand All @@ -138,8 +157,8 @@ export default class ColorControl extends React.Component {
?
</ColorSwatch>
{this.state.showColorPicker && (
<ColorPickerContainer>
<ClickOutsideDiv onClick={this.handleClose} />
<ColorPickerContainer data-testid="color-picker-container">
<ClickOutsideDiv onClick={this.handleClose} data-testid="picker-bg" />
<ChromePicker
color={value || ''}
onChange={this.handleChange}
Expand All @@ -153,7 +172,7 @@ export default class ColorControl extends React.Component {
id={forID}
className={classNameWrapper}
value={value || ''}
onChange={e => onChange(e.target.value)}
onChange={this.handleInputChange}
onFocus={setActiveStyle}
onBlur={setInactiveStyle}
style={{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Color widget field.allowInput is false renders input as readonly 1`] = `
<input
class="test-classname"
id="test-string"
readonly=""
style="padding-left: 75px; padding-right: 70px; color: rgb(187, 187, 187);"
type="text"
value=""
/>
`;
130 changes: 130 additions & 0 deletions packages/netlify-cms-widget-colorstring/src/__tests__/color.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import React from 'react';
import { fromJS } from 'immutable';
import { render, fireEvent } from '@testing-library/react';

import { NetlifyCmsWidgetColorString } from '../';

const ColorControl = NetlifyCmsWidgetColorString.controlComponent;

const fieldSettings = {
allowInput: false,
};

function setup({ field, defaultValue } = {}) {
const setActiveSpy = jest.fn();
const setInactiveSpy = jest.fn();
const onChangeSpy = jest.fn();

const helpers = render(
<ColorControl
field={field}
value={defaultValue}
onChange={onChangeSpy}
forID="test-string"
classNameWrapper="test-classname"
setActiveStyle={setActiveSpy}
setInactiveStyle={setInactiveSpy}
/>,
);

const input = helpers.container.querySelector('input');

jest.useFakeTimers();

return {
...helpers,
setActiveSpy,
setInactiveSpy,
onChangeSpy,
input,
};
}

describe('Color widget', () => {
it('renders with default value', () => {
const field = fromJS(fieldSettings);
const testValue = '#fff000';
const { input } = setup({ field, defaultValue: testValue });

expect(input.value).toEqual(testValue);
});

describe('field.allowInput is false', () => {
it('renders input as readonly', () => {
const field = fromJS(fieldSettings);
const { input } = setup({ field });

expect(input).toMatchSnapshot();
});

it('opens picker on input click', () => {
const field = fromJS(fieldSettings);
const { input, queryByTestId } = setup({ field });

fireEvent.click(input);

expect(queryByTestId('color-picker-container')).not.toBeNull();
});

it('displays clear button when input is present', () => {
const field = fromJS(fieldSettings);
const { queryByTestId } = setup({ field, defaultValue: '#fff000' });

expect(queryByTestId('clear-btn-wrapper')).not.toBeNull();
});
});

describe('field.allowInput is true', () => {
const field = fromJS({ ...fieldSettings, allowInput: true });

it('calls onChange when input changes', () => {
const testValue = '#fff000';
const { input, onChangeSpy } = setup({ field });

fireEvent.focus(input);
fireEvent.change(input, { target: { value: testValue } });

jest.runAllTimers();

expect(onChangeSpy).toHaveBeenCalledTimes(1);
expect(onChangeSpy).toHaveBeenCalledWith(testValue);
});

it('sets input value', () => {
const testValue = '#fff000';
const { input } = setup({ field });

fireEvent.focus(input);
fireEvent.change(input, { target: { value: testValue } });

jest.runAllTimers();

expect(input.value).toEqual(testValue);
});

it('does not open picker on input click', () => {
const { input, queryByTestId } = setup({ field });

fireEvent.click(input);

expect(queryByTestId('color-picker-container')).toBeNull();
});

it('calls setActiveStyle when input focused', () => {
const { input, setActiveSpy } = setup({ field });

fireEvent.focus(input);

expect(setActiveSpy).toHaveBeenCalledTimes(1);
});

it('calls setInactiveSpy when input blurred', () => {
const { input, setInactiveSpy } = setup({ field });

fireEvent.focus(input);
fireEvent.blur(input);

expect(setInactiveSpy).toHaveBeenCalledTimes(1);
});
});
});
15 changes: 11 additions & 4 deletions packages/netlify-cms-widget-datetime/src/DateTimeControl.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import reactDateTimeStyles from 'react-datetime/css/react-datetime.css';
import DateTime from 'react-datetime';
import moment from 'moment';
import { buttons } from 'netlify-cms-ui-default';
import { debounce } from 'lodash';

function NowButton({ t, handleChange }) {
return (
Expand Down Expand Up @@ -44,6 +45,8 @@ export default class DateTimeControl extends React.Component {
value: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
};

state = { value: this.props.value };

getFormats() {
const { field } = this.props;
const format = field.get('format');
Expand Down Expand Up @@ -99,6 +102,8 @@ export default class DateTimeControl extends React.Component {
isValidDate = datetime =>
moment.isMoment(datetime) || datetime instanceof Date || datetime === '';

debounceOnChange = debounce(value => this.props.onChange(value), 300);

handleChange = datetime => {
/**
* Set the date only if it is valid.
Expand All @@ -107,7 +112,6 @@ export default class DateTimeControl extends React.Component {
return;
}

const { onChange } = this.props;
const { format } = this.formats;

/**
Expand All @@ -116,10 +120,12 @@ export default class DateTimeControl extends React.Component {
*/
if (format) {
const formattedValue = datetime ? moment(datetime).format(format) : '';
onChange(formattedValue);
this.setState({ value: formattedValue });
this.debounceOnChange(formattedValue);
} else {
const value = moment.isMoment(datetime) ? datetime.toDate() : datetime;
onChange(value);
this.setState({ value });
this.debounceOnChange(value);
}
};

Expand All @@ -140,7 +146,8 @@ export default class DateTimeControl extends React.Component {
};

render() {
const { forID, value, classNameWrapper, setActiveStyle, t, isDisabled } = this.props;
const { forID, classNameWrapper, setActiveStyle, t, isDisabled } = this.props;
const { value } = this.state;
const { format, dateFormat, timeFormat } = this.formats;

return (
Expand Down
Loading
Loading