mirror of
https://github.com/plankanban/planka.git
synced 2025-07-18 20:59:44 +02:00
Allow creating label without name
This commit is contained in:
parent
d88bec8b6b
commit
9ebc82bf22
9 changed files with 31 additions and 51 deletions
|
@ -48,7 +48,7 @@ const Label = React.memo(({
|
|||
className={classNames(styles.wrapper, onClick && styles.hoverable)}
|
||||
style={style}
|
||||
>
|
||||
{name}
|
||||
{name || '\u00A0'}
|
||||
</div>
|
||||
);
|
||||
|
||||
|
@ -62,14 +62,15 @@ const Label = React.memo(({
|
|||
});
|
||||
|
||||
Label.propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
color: PropTypes.oneOf(LabelColors.KEYS).isRequired, // TODO: without color
|
||||
name: PropTypes.string,
|
||||
color: PropTypes.oneOf(LabelColors.KEYS).isRequired,
|
||||
size: PropTypes.oneOf(Object.values(SIZES)),
|
||||
isDisabled: PropTypes.bool,
|
||||
onClick: PropTypes.func,
|
||||
};
|
||||
|
||||
Label.defaultProps = {
|
||||
name: undefined,
|
||||
size: SIZES.MEDIUM,
|
||||
isDisabled: false,
|
||||
onClick: undefined,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useRef } from 'react';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button, Form } from 'semantic-ui-react';
|
||||
|
@ -18,19 +18,12 @@ const AddStep = React.memo(({ onCreate, onBack }) => {
|
|||
color: LabelColors.KEYS[0],
|
||||
}));
|
||||
|
||||
const editor = useRef(null);
|
||||
|
||||
const handleSubmit = useDeepCompareCallback(() => {
|
||||
const cleanData = {
|
||||
...data,
|
||||
name: data.name.trim(),
|
||||
name: data.name.trim() || null,
|
||||
};
|
||||
|
||||
if (!cleanData.name) {
|
||||
editor.current.selectNameField();
|
||||
return;
|
||||
}
|
||||
|
||||
onCreate(cleanData);
|
||||
onBack();
|
||||
}, [data, onCreate, onBack]);
|
||||
|
@ -44,7 +37,7 @@ const AddStep = React.memo(({ onCreate, onBack }) => {
|
|||
</Popup.Header>
|
||||
<Popup.Content>
|
||||
<Form onSubmit={handleSubmit}>
|
||||
<Editor ref={editor} data={data} onFieldChange={handleFieldChange} />
|
||||
<Editor data={data} onFieldChange={handleFieldChange} />
|
||||
<Button positive content={t('action.createLabel')} className={styles.submitButton} />
|
||||
</Form>
|
||||
</Popup.Content>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import dequal from 'dequal';
|
||||
import React, { useCallback, useRef } from 'react';
|
||||
import React, { useCallback } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button, Form } from 'semantic-ui-react';
|
||||
|
@ -22,26 +22,19 @@ const EditStep = React.memo(({
|
|||
const [t] = useTranslation();
|
||||
|
||||
const [data, handleFieldChange] = useForm(() => ({
|
||||
name: '',
|
||||
color: LabelColors.KEYS[0],
|
||||
...defaultData,
|
||||
name: defaultData.name || '',
|
||||
}));
|
||||
|
||||
const [step, openStep, handleBack] = useSteps();
|
||||
|
||||
const editor = useRef(null);
|
||||
|
||||
const handleSubmit = useDeepCompareCallback(() => {
|
||||
const cleanData = {
|
||||
...data,
|
||||
name: data.name.trim(),
|
||||
name: data.name.trim() || null,
|
||||
};
|
||||
|
||||
if (!cleanData.name) {
|
||||
editor.current.selectNameField();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dequal(cleanData, defaultData)) {
|
||||
onUpdate(cleanData);
|
||||
}
|
||||
|
@ -76,7 +69,7 @@ const EditStep = React.memo(({
|
|||
</Popup.Header>
|
||||
<Popup.Content>
|
||||
<Form onSubmit={handleSubmit}>
|
||||
<Editor ref={editor} data={data} onFieldChange={handleFieldChange} />
|
||||
<Editor data={data} onFieldChange={handleFieldChange} />
|
||||
<Button positive content={t('action.save')} />
|
||||
</Form>
|
||||
<Button
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import React, {
|
||||
useCallback, useEffect, useImperativeHandle, useRef,
|
||||
} from 'react';
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
@ -11,27 +9,15 @@ import LabelColors from '../../constants/LabelColors';
|
|||
|
||||
import styles from './Editor.module.css';
|
||||
|
||||
const Editor = React.forwardRef(({ data, onFieldChange }, ref) => {
|
||||
const Editor = React.memo(({ data, onFieldChange }) => {
|
||||
const [t] = useTranslation();
|
||||
|
||||
const nameField = useRef(null);
|
||||
|
||||
const selectNameField = useCallback(() => {
|
||||
useEffect(() => {
|
||||
nameField.current.select();
|
||||
}, []);
|
||||
|
||||
useImperativeHandle(
|
||||
ref,
|
||||
() => ({
|
||||
selectNameField,
|
||||
}),
|
||||
[selectNameField],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
selectNameField();
|
||||
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={styles.text}>{t('common.title')}</div>
|
||||
|
@ -71,4 +57,4 @@ Editor.propTypes = {
|
|||
onFieldChange: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default React.memo(Editor);
|
||||
export default Editor;
|
||||
|
|
|
@ -43,7 +43,7 @@ const Item = React.memo(({
|
|||
});
|
||||
|
||||
Item.propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
name: PropTypes.string,
|
||||
color: PropTypes.string.isRequired,
|
||||
isPersisted: PropTypes.bool.isRequired,
|
||||
isActive: PropTypes.bool.isRequired,
|
||||
|
@ -52,4 +52,8 @@ Item.propTypes = {
|
|||
onEdit: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
Item.defaultProps = {
|
||||
name: undefined,
|
||||
};
|
||||
|
||||
export default Item;
|
||||
|
|
|
@ -12,12 +12,13 @@ module.exports = {
|
|||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
required: true
|
||||
isNotEmptyString: true,
|
||||
allowNull: true
|
||||
},
|
||||
color: {
|
||||
type: 'string',
|
||||
isIn: Label.COLORS,
|
||||
allowNull: true
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -12,12 +12,13 @@ module.exports = {
|
|||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
isNotEmptyString: true
|
||||
isNotEmptyString: true,
|
||||
allowNull: true
|
||||
},
|
||||
color: {
|
||||
type: 'string',
|
||||
isIn: Label.COLORS,
|
||||
allowNull: true
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -28,12 +28,13 @@ module.exports = {
|
|||
|
||||
name: {
|
||||
type: 'string',
|
||||
required: true
|
||||
isNotEmptyString: true,
|
||||
allowNull: true
|
||||
},
|
||||
color: {
|
||||
type: 'string',
|
||||
isIn: COLORS,
|
||||
allowNull: true
|
||||
required: true
|
||||
},
|
||||
|
||||
// ╔═╗╔╦╗╔╗ ╔═╗╔╦╗╔═╗
|
||||
|
|
|
@ -6,8 +6,8 @@ module.exports.up = knex =>
|
|||
|
||||
table.integer('board_id').notNullable();
|
||||
|
||||
table.text('name').notNullable();
|
||||
table.text('color');
|
||||
table.text('name');
|
||||
table.text('color').notNullable();
|
||||
|
||||
table.timestamp('created_at', true);
|
||||
table.timestamp('updated_at', true);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue