// Copyright 2021 99cloud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { Input, Tag, Menu, Divider, Button, Checkbox, Row, Col } from 'antd';
import { CloseOutlined, SearchOutlined } from '@ant-design/icons';
import classnames from 'classnames';
import { isEmpty, isBoolean } from 'lodash';
import styles from './index.less';
const option = PropTypes.shape({
label: PropTypes.string.isRequired,
key: PropTypes.oneOfType([
PropTypes.string.isRequired,
PropTypes.bool.isRequired,
]),
component: PropTypes.node,
});
const filterParam = PropTypes.shape({
label: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
isSingle: PropTypes.bool,
isServer: PropTypes.bool,
allowed: PropTypes.func,
options: PropTypes.arrayOf(option),
isTime: PropTypes.bool,
});
export const getTags = (initValue, filterParams) => {
if (!initValue || isEmpty(initValue)) {
return {};
}
if (isEmpty(filterParams)) {
return {};
}
const tags = [];
const checkValues = [];
Object.keys(initValue).forEach((key) => {
const item = filterParams.find((it) => it.name === key);
if (item) {
const { options = [] } = item;
const value = initValue[key];
if (options.length) {
const optionItem = options.find((op) => op.key === value);
if (optionItem && optionItem.isQuick) {
checkValues.push(`${item.name}--${value}`);
}
}
tags.push({
value,
filter: item,
});
}
});
return {
tags,
checkValues,
};
};
class MagicInput extends PureComponent {
static propTypes = {
filterParams: PropTypes.arrayOf(filterParam),
// eslint-disable-next-line react/no-unused-prop-types
initValue: PropTypes.object,
placeholder: PropTypes.string,
onInputChange: PropTypes.func,
onInputFocus: PropTypes.func,
};
static defaultProps = {
filterParams: [],
initValue: {},
placeholder: t('Click here for filters.'),
};
constructor(props) {
super(props);
this.inputRef = React.createRef();
this.state = {
tags: [],
currentFilter: null,
isFocus: false,
optionClear: false,
checkValues: [],
};
}
componentDidMount() {
this.initTags(this.props);
}
getFilterParams = () => {
// eslint-disable-next-line no-shadow
const { filterParams } = this.props;
const { tags } = this.state;
const filters = [];
filterParams.forEach((item) => {
const alreadyTag = tags.find((it) => it.filter.name === item.name);
if (!alreadyTag) {
filters.push(item);
}
});
return filters;
};
onTagsChange = () => {
const { onInputChange } = this.props;
const { tags } = this.state;
onInputChange && onInputChange(tags);
};
onFocusChange = (value) => {
const { onInputFocus } = this.props;
onInputFocus && onInputFocus(value);
};
getDefaultFilter = () => {
const { filterParams } = this.props;
return filterParams.find((it) => !it.options);
};
handleEnter = (e) => {
e && e.preventDefault();
e && e.stopPropagation();
const { value } = e.currentTarget;
if (!value) {
return;
}
this.updateInput(value);
};
handleBlur = () => {
const { currentFilter } = this.state;
if (currentFilter) {
this.setState({
isFocus: true,
});
this.onFocusChange(true);
} else {
this.onFocusChange(false);
}
};
handleKeyUp = (e) => {
if (e.keyCode === 8 || e.keyCode === 46) {
const { currentFilter, tags } = this.state;
const { value } = this.inputRef.current.state;
if (currentFilter && isEmpty(value)) {
this.setState({
currentFilter: null,
});
} else if (tags.length > 0 && isEmpty(value)) {
this.handleTagClose(tags[tags.length - 1].filter.name);
}
}
};
handleFocus = () => {
this.setState({
isFocus: true,
});
this.onFocusChange(true);
};
handleInputChange = (e) => {
this.setState({
inputValue: e.target.value,
});
};
handleTagClose = (name) => {
const { tags, checkValues } = this.state;
const newTags = tags.filter((it) => it.filter.name !== name);
const leftCheckValues = checkValues.filter(
(it) => it.split('--')[0] !== name
);
this.setState(
{
tags: newTags,
optionClear: false,
checkValues: leftCheckValues,
},
() => {
this.onTagsChange();
}
);
};
handleOptionClick = ({ key }) => {
let value;
if (key === 'true') {
value = true;
} else {
value = key === 'false' ? false : key;
}
this.updateInput(value);
};
handleSelectFilter = ({ key }) => {
// eslint-disable-next-line no-shadow
const { filterParams } = this.props;
const filter = filterParams.find((it) => it.name === key);
this.setState(
{
currentFilter: filter,
isFocus: true,
},
() => {
this.inputRef.current.focus();
this.onFocusChange(true);
}
);
};
initTags(props) {
const { initValue, filterParams } = props;
const { tags = [], checkValues } = getTags(initValue, filterParams);
if (!tags.length) {
return;
}
this.setState(
{
tags,
checkValues,
},
() => {
this.onTagsChange();
}
);
}
renderKey() {
const { currentFilter } = this.state;
if (!currentFilter) {
return null;
}
return (
{`${currentFilter.label}`}