Skip to content

Commit

Permalink
chore(3 widgets): add prefix & suffix labels
Browse files Browse the repository at this point in the history
Those 3 widgets are Boolean, Number, String

- update 3 widgets UI to display prefix & suffix
- refactor BooleanControl.js code structure
- update document for 3 widgets
- update demo config `dev-test/`
  • Loading branch information
ngdangtu-vn committed Oct 21, 2023
1 parent 26f650b commit e9c3a9e
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 55 deletions.
26 changes: 23 additions & 3 deletions dev-test/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,31 @@ collections: # A list of collections the CMS should be able to edit
display_fields: ['title', 'datetime']
search_fields: ['title', 'body']
value_field: 'title'
- { label: 'Title', name: 'title', widget: 'string' }
- { label: 'Boolean', name: 'boolean', widget: 'boolean', default: true }
- {
label: 'Title',
name: 'title',
widget: 'string',
prefix: 'This string:',
suffix: 'is a title'
}
- {
label: 'Boolean',
name: 'boolean',
widget: 'boolean',
prefix: 'OFF',
suffix: 'ON',
hint: 'Toggle this to switch on/off',
default: true
}
- { label: 'Map', name: 'map', widget: 'map' }
- { label: 'Text', name: 'text', widget: 'text', hint: 'Plain text, not markdown' }
- { label: 'Number', name: 'number', widget: 'number', hint: 'To infinity and beyond!' }
- {
label: 'Number',
name: 'number',
widget: 'number',
suffix: 'px',
hint: 'To infinity and beyond!'
}
- { label: 'Markdown', name: 'markdown', widget: 'markdown' }
- { label: 'Datetime', name: 'datetime', widget: 'datetime' }
- { label: 'Image', name: 'image', widget: 'image' }
Expand Down
59 changes: 36 additions & 23 deletions packages/decap-cms-widget-boolean/src/BooleanControl.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import { css } from '@emotion/react';
import { Toggle, ToggleBackground, colors } from 'decap-cms-ui-default';

const innerWrapper = css`
display: flex;
align-items: center;
`

function BooleanBackground({ isActive, ...props }) {
return (
<ToggleBackground
Expand All @@ -16,34 +21,42 @@ function BooleanBackground({ isActive, ...props }) {
}

export default class BooleanControl extends React.Component {
static propTypes = {
field: ImmutablePropTypes.map.isRequired,
onChange: PropTypes.func.isRequired,
classNameWrapper: PropTypes.string.isRequired,
setActiveStyle: PropTypes.func.isRequired,
setInactiveStyle: PropTypes.func.isRequired,
forID: PropTypes.string,
value: PropTypes.bool,
}

static defaultProps = {
value: false,
}

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

const prefix = field.get('prefix', false);
const suffix = field.get('suffix', false);

return (
<div className={classNameWrapper}>
<Toggle
id={forID}
active={value}
onChange={onChange}
onFocus={setActiveStyle}
onBlur={setInactiveStyle}
Background={BooleanBackground}
/>
<div css={innerWrapper}>
{prefix && (<span>{prefix}&nbsp;</span>)}
<Toggle
id={forID}
active={value}
onChange={onChange}
onFocus={setActiveStyle}
onBlur={setInactiveStyle}
Background={BooleanBackground}
/>
{suffix && (<span>&nbsp;{suffix}</span>)}
</div>
</div>
);
}
}

BooleanControl.propTypes = {
field: ImmutablePropTypes.map.isRequired,
onChange: PropTypes.func.isRequired,
classNameWrapper: PropTypes.string.isRequired,
setActiveStyle: PropTypes.func.isRequired,
setInactiveStyle: PropTypes.func.isRequired,
forID: PropTypes.string,
value: PropTypes.bool,
};

BooleanControl.defaultProps = {
value: false,
};
41 changes: 29 additions & 12 deletions packages/decap-cms-widget-number/src/NumberControl.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import React from 'react';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { css } from '@emotion/core';

const ValidationErrorTypes = {
PRESENCE: 'PRESENCE',
PATTERN: 'PATTERN',
RANGE: 'RANGE',
CUSTOM: 'CUSTOM',
};

const innerWrapper = css`
display: flex;
align-items: baseline;
`

export function validateMinMax(value, min, max, field, t) {
let error;

Expand Down Expand Up @@ -100,19 +107,29 @@ export default class NumberControl extends React.Component {
const min = field.get('min', '');
const max = field.get('max', '');
const step = field.get('step', field.get('value_type') === 'int' ? 1 : '');

const prefix = field.get('prefix', false);
const suffix = field.get('suffix', false);

return (
<input
type="number"
id={forID}
className={classNameWrapper}
onFocus={setActiveStyle}
onBlur={setInactiveStyle}
value={value || (value === 0 ? value : '')}
step={step}
min={min}
max={max}
onChange={this.handleChange}
/>
<div className={classNameWrapper}>
<div css={innerWrapper}>
{prefix && (<span>{prefix}&nbsp;</span>)}
<input
type="number"
id={forID}
onFocus={setActiveStyle}
onBlur={setInactiveStyle}
value={value || (value === 0 ? value : '')}
step={step}
min={min}
max={max}
onChange={this.handleChange}
css={css`flex-grow: 1`}
/>
{suffix && (<span>&nbsp;{suffix}</span>)}
</div>
</div>
);
}
}
43 changes: 30 additions & 13 deletions packages/decap-cms-widget-string/src/StringControl.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
import React from 'react';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { css } from '@emotion/core';

const innerWrapper = css`
display: flex;
align-items: baseline;
`

export default class StringControl extends React.Component {
static propTypes = {
field: ImmutablePropTypes.map.isRequired,
onChange: PropTypes.func.isRequired,
forID: PropTypes.string,
value: PropTypes.node,
Expand Down Expand Up @@ -41,21 +49,30 @@ export default class StringControl extends React.Component {
};

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

const prefix = field.get('prefix', false);
const suffix = field.get('suffix', false);

return (
<input
ref={el => {
this._el = el;
}}
type="text"
id={forID}
className={classNameWrapper}
value={value || ''}
onChange={this.handleChange}
onFocus={setActiveStyle}
onBlur={setInactiveStyle}
/>
<div className={classNameWrapper}>
<div css={innerWrapper}>
{prefix && (<span>{prefix}&nbsp;</span>)}
<input
ref={el => {
this._el = el;
}}
type="text"
id={forID}
value={value || ''}
onChange={this.handleChange}
onFocus={setActiveStyle}
onBlur={setInactiveStyle}
css={css`flex-grow: 1`}
/>
{suffix && (<span>&nbsp;{suffix}</span>)}
</div>
</div>
);
}
}
4 changes: 1 addition & 3 deletions packages/decap-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,5 @@
"engines": {
"node": ">=v10.22.1"
},
"bin": {
"decap-server": "./dist/index.js"
}
"bin": "./dist/index.js"
}
9 changes: 8 additions & 1 deletion website/content/docs/widgets/boolean.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,14 @@ The boolean widget translates a toggle switch input to a true/false value.
- **Data type:** boolean
- **Options:**
- `default`: accepts `true` or `false`; defaults to `false` when `required` is set to `false`
- `prefix`: display a message before the toggle; accepts a string; defaults to an empty string
- `suffix`: display a message after the toggle; accepts a string; defaults to an empty string
- **Example:**
```yaml
- {label: "Draft", name: "draft", widget: "boolean", default: true}
- label: "Draft"
name: "draft"
widget: "boolean"
prefix: "OFF"
default: true
suffix: "ON"
```
3 changes: 3 additions & 0 deletions website/content/docs/widgets/number.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ The number widget uses an HTML number input, saving the value as a string, integ
- `min`: accepts a number for minimum value accepted; unset by default
- `max`: accepts a number for maximum value accepted; unset by default
- `step`: accepts a number for stepping up/down values in the input; 1 by default
- `prefix`: display a message before the number input; accepts a string; defaults to an empty string
- `suffix`: display a message after the number input; accepts a string; defaults to an empty string
- **Example:**
```yaml
- label: "Puppy Count"
Expand All @@ -24,4 +26,5 @@ The number widget uses an HTML number input, saving the value as a string, integ
min: 1
max: 101
step: 2
suffix: puppies
```
2 changes: 2 additions & 0 deletions website/content/docs/widgets/string.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ The string widget translates a basic text input to a string value. For larger te
- **Data type:** string
- **Options:**
- `default`: accepts a string; defaults to an empty string
- `prefix`: display a message before the string input; accepts a string; defaults to an empty string
- `suffix`: display a message after the string input; accepts a string; defaults to an empty string
- **Example:**
```yaml
- {label: "Title", name: "title", widget: "string"}
Expand Down

0 comments on commit e9c3a9e

Please sign in to comment.