1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-17 15:53:28 +00:00

Change tag list UI (#5637)

* 01 change file tags list

* 02 change select tags UI

* change edit icons
This commit is contained in:
Michael An
2023-09-13 23:12:23 +08:00
committed by GitHub
parent 14ce391007
commit 754d9c0fe8
22 changed files with 752 additions and 141 deletions

View File

@@ -0,0 +1,22 @@
import React from 'react';
import PropTypes from 'prop-types';
import '../../css/common-add-tool.css';
function CommonAddTool(props) {
const { callBack, footerName, className, addIconClassName } = props;
return (
<div className={`add-item-btn ${className ? className : ''}`} onClick={(e) => {callBack(e);}}>
<span className={`fas fa-plus mr-2 ${addIconClassName || ''}`}></span>
<span className='add-new-option' title={footerName}>{footerName}</span>
</div>
);
}
CommonAddTool.propTypes = {
className: PropTypes.string,
addIconClassName: PropTypes.string,
footerName: PropTypes.string.isRequired,
callBack: PropTypes.func.isRequired,
};
export default CommonAddTool;

View File

@@ -0,0 +1,101 @@
import React from 'react';
import { Popover } from 'reactstrap';
import PropTypes from 'prop-types';
import { KeyCodes } from '../../constants';
const propTypes = {
target: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired,
boundariesElement: PropTypes.object,
innerClassName: PropTypes.string,
popoverClassName: PropTypes.string,
children: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
hideSeahubPopover: PropTypes.func.isRequired,
hideSeahubPopoverWithEsc: PropTypes.func,
hideArrow: PropTypes.bool,
canHideSeahubPopover: PropTypes.bool,
placement: PropTypes.string,
modifiers: PropTypes.object
};
class SeahubPopover extends React.Component {
SeahubPopoverRef = null;
isSelectOpen = false;
componentDidMount() {
document.addEventListener('mousedown', this.onMouseDown, true);
document.addEventListener('keydown', this.onKeyDown);
}
componentWillUnmount() {
document.removeEventListener('mousedown', this.onMouseDown, true);
document.removeEventListener('keydown', this.onKeyDown);
}
getEventClassName = (e) => {
// svg mouseEvent event.target.className is an object
if (!e || !e.target) return '';
return e.target.getAttribute('class') || '';
};
onKeyDown = (e) => {
const { canHideSeahubPopover, hideSeahubPopoverWithEsc } = this.props;
if (e.keyCode === KeyCodes.Escape && typeof hideSeahubPopoverWithEsc === 'function' && !this.isSelectOpen) {
e.preventDefault();
hideSeahubPopoverWithEsc();
} else if (e.keyCode === KeyCodes.Enter) {
// Resolve the default behavior of the enter key when entering formulas is blocked
if (canHideSeahubPopover) return;
e.stopImmediatePropagation();
}
};
onMouseDown = (e) => {
if (!this.props.canHideSeahubPopover) return;
if (this.SeahubPopoverRef && e && this.getEventClassName(e).indexOf('popover') === -1 && !this.SeahubPopoverRef.contains(e.target)) {
this.props.hideSeahubPopover(e);
}
};
onPopoverInsideClick = (e) => {
e.stopPropagation();
};
render() {
const {
target, boundariesElement, innerClassName, popoverClassName, hideArrow, modifiers,
placement,
} = this.props;
let additionalProps = {};
if (boundariesElement) {
additionalProps.boundariesElement = boundariesElement;
}
return (
<Popover
placement={placement}
isOpen={true}
target={target}
fade={false}
hideArrow={hideArrow}
innerClassName={innerClassName}
className={popoverClassName}
modifiers={modifiers}
{...additionalProps}
>
<div ref={ref => this.SeahubPopoverRef = ref} onClick={this.onPopoverInsideClick}>
{this.props.children}
</div>
</Popover>
);
}
}
SeahubPopover.defaultProps = {
placement: 'bottom-start',
hideArrow: true,
canHideSeahubPopover: true
};
SeahubPopover.propTypes = propTypes;
export default SeahubPopover;

View File

@@ -0,0 +1,144 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
const propTypes = {
placeholder: PropTypes.string,
autoFocus: PropTypes.bool,
className: PropTypes.string,
onChange: PropTypes.func.isRequired,
onKeyDown: PropTypes.func,
wait: PropTypes.number,
disabled: PropTypes.bool,
style: PropTypes.object,
isClearable: PropTypes.bool,
clearValue: PropTypes.func,
clearClassName: PropTypes.string,
components: PropTypes.object,
value: PropTypes.string,
};
class SearchInput extends Component {
constructor(props) {
super(props);
this.state = {
searchValue: props.value,
};
this.isInputtingChinese = false;
this.timer = null;
this.inputRef = null;
}
componentDidMount() {
if (this.props.autoFocus && this.inputRef && this.inputRef !== document.activeElement) {
setTimeout(() => {
this.inputRef.focus();
}, 0);
}
}
componentWillReceiveProps(nextProps) {
if (nextProps.value !== this.props.value) {
this.setState({searchValue: nextProps.value});
}
}
componentWillUnmount() {
this.timer && clearTimeout(this.timer);
this.timer = null;
this.inputRef = null;
}
onCompositionStart = () => {
this.isInputtingChinese = true;
};
onChange = (e) => {
this.timer && clearTimeout(this.timer);
const { onChange, wait } = this.props;
let text = e.target.value;
this.setState({searchValue: text || ''}, () => {
if (this.isInputtingChinese) return;
this.timer = setTimeout(() => {
onChange && onChange(this.state.searchValue.trim());
}, wait);
});
};
onCompositionEnd = (e) => {
this.isInputtingChinese = false;
this.onChange(e);
};
clearSearch = () => {
const { clearValue } = this.props;
this.setState({searchValue: ''}, () => {
clearValue && clearValue();
});
};
setFocus = (isSelectAllText) => {
if (this.inputRef === document.activeElement) return;
this.inputRef.focus();
if (isSelectAllText) {
const txtLength = this.state.searchValue.length;
this.inputRef.setSelectionRange(0, txtLength);
}
};
isFunction = (functionToCheck) => {
const getType = {};
return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
};
renderClear = () => {
const { isClearable, clearClassName, components = {} } = this.props;
const { searchValue } = this.state;
if (!isClearable || !searchValue) return null;
const { ClearIndicator } = components;
if (React.isValidElement(ClearIndicator)) {
return React.cloneElement(ClearIndicator, {clearValue: this.clearSearch});
} else if (this.isFunction(ClearIndicator)) {
return <ClearIndicator clearValue={this.clearSearch} />;
}
return (
<i className={classnames('search-text-clear input-icon-addon', clearClassName)} onClick={this.clearSearch}>×</i>
);
};
render() {
const { placeholder, autoFocus, className, onKeyDown, disabled, style } = this.props;
const { searchValue } = this.state;
return (
<Fragment>
<input
type="text"
value={searchValue}
className={classnames('form-control', className)}
onChange={this.onChange}
autoFocus={autoFocus}
placeholder={placeholder}
onCompositionStart={this.onCompositionStart}
onCompositionEnd={this.onCompositionEnd}
onKeyDown={onKeyDown}
disabled={disabled}
style={style}
ref={ref => this.inputRef = ref}
/>
{this.renderClear()}
</Fragment>
);
}
}
SearchInput.propTypes = propTypes;
SearchInput.defaultProps = {
wait: 100,
disabled: false,
value: '',
};
export default SearchInput;