mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-02 23:48:47 +00:00
[advanced search] fixed and improved 'date picker' (#4614)
* fixed UI * added 'clear', 'disabledDate', 'click outside to close' * allow user to choose the same day for start & end date
This commit is contained in:
@@ -14,8 +14,6 @@ const propsTypes = {
|
|||||||
onChange: PropTypes.func.isRequired
|
onChange: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
const FORMAT = 'YYYY-MM-DD HH:mm';
|
|
||||||
|
|
||||||
class Picker extends React.Component {
|
class Picker extends React.Component {
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@@ -24,7 +22,7 @@ class Picker extends React.Component {
|
|||||||
this.calendarContainerRef = React.createRef();
|
this.calendarContainerRef = React.createRef();
|
||||||
this.inputRef = React.createRef();
|
this.inputRef = React.createRef();
|
||||||
this.state = {
|
this.state = {
|
||||||
isOpen: true
|
isOpen: false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,12 +62,20 @@ class Picker extends React.Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const props = this.props;
|
const props = this.props;
|
||||||
|
|
||||||
|
let showHourAndMinute = true; // default: true
|
||||||
|
if (props.showHourAndMinute != undefined) {
|
||||||
|
showHourAndMinute = props.showHourAndMinute;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FORMAT = showHourAndMinute ? 'YYYY-MM-DD HH:mm' : 'YYYY-MM-DD';
|
||||||
|
|
||||||
const calendar = (<Calendar
|
const calendar = (<Calendar
|
||||||
defaultValue={this.defaultCalendarValue}
|
defaultValue={this.defaultCalendarValue}
|
||||||
disabledDate={props.disabledDate}
|
disabledDate={props.disabledDate}
|
||||||
format={FORMAT}
|
format={FORMAT}
|
||||||
locale={translateCalendar()}
|
locale={translateCalendar()}
|
||||||
showHourAndMinute={true}
|
showHourAndMinute={showHourAndMinute}
|
||||||
/>);
|
/>);
|
||||||
return (
|
return (
|
||||||
<DatePicker
|
<DatePicker
|
||||||
|
@@ -1,9 +1,10 @@
|
|||||||
import React, { Fragment } from 'react';
|
import React, { Fragment } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import MediaQuery from 'react-responsive';
|
import MediaQuery from 'react-responsive';
|
||||||
import { gettext, lang } from '../../utils/constants';
|
import moment from 'moment';
|
||||||
import { Button, Col, Collapse, CustomInput, FormGroup, Input, Label, Row, InputGroupAddon, InputGroup } from 'reactstrap';
|
import { Button, Col, Collapse, CustomInput, FormGroup, Input, Label, Row, InputGroupAddon, InputGroup } from 'reactstrap';
|
||||||
import SelectDate from '@seafile/seafile-editor/dist/components/calander';
|
import { gettext } from '../../utils/constants';
|
||||||
|
import DateTimePicker from '../../components/date-and-time-picker';
|
||||||
|
|
||||||
const { repo_name, search_repo } = window.search.pageOptions;
|
const { repo_name, search_repo } = window.search.pageOptions;
|
||||||
|
|
||||||
@@ -24,6 +25,34 @@ class AdvancedSearch extends React.Component {
|
|||||||
return ftype;
|
return ftype;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
disabledStartDate = (startValue) => {
|
||||||
|
if (!startValue) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isAfterToday = startValue.isAfter(moment(), 'day');
|
||||||
|
const { time_to } = this.props.stateAndValues;
|
||||||
|
const endValue = time_to;
|
||||||
|
if (!endValue) {
|
||||||
|
return isAfterToday;
|
||||||
|
}
|
||||||
|
return startValue.isAfter(endValue) || isAfterToday;
|
||||||
|
}
|
||||||
|
|
||||||
|
disabledEndDate = (endValue) => {
|
||||||
|
if (!endValue) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isAfterToday = endValue.isAfter(moment(), 'day');
|
||||||
|
const { time_from } = this.props.stateAndValues;
|
||||||
|
const startValue = time_from;
|
||||||
|
if (!startValue) {
|
||||||
|
return isAfterToday;
|
||||||
|
}
|
||||||
|
return endValue.isBefore(startValue) || isAfterToday;
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { stateAndValues } = this.props;
|
const { stateAndValues } = this.props;
|
||||||
const { errorDateMsg, errorSizeMsg } = stateAndValues;
|
const { errorDateMsg, errorSizeMsg } = stateAndValues;
|
||||||
@@ -43,7 +72,7 @@ class AdvancedSearch extends React.Component {
|
|||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
{(time_from && time_to ) &&
|
{(time_from && time_to ) &&
|
||||||
<span className="mr-4">{gettext('Last Update')}{': '}{time_from}{' '}{gettext('to')}{' '}{time_to}</span>
|
<span className="mr-4">{gettext('Last Update')}{': '}{time_from.format('YYYY-MM-DD')}{' '}{gettext('to')}{' '}{time_to.format('YYYY-MM-DD')}</span>
|
||||||
}
|
}
|
||||||
{(size_from && size_to) &&
|
{(size_from && size_to) &&
|
||||||
<span className="mr-4">{gettext('Size')}{': '}{size_from}{'MB - '}{size_to}{'MB'}</span>
|
<span className="mr-4">{gettext('Size')}{': '}{size_from}{'MB - '}{size_to}{'MB'}</span>
|
||||||
@@ -168,19 +197,23 @@ class AdvancedSearch extends React.Component {
|
|||||||
<Row>
|
<Row>
|
||||||
<Col md="2" lg="2" className="mt-2">{gettext('Last Update')}{': '}</Col>
|
<Col md="2" lg="2" className="mt-2">{gettext('Last Update')}{': '}</Col>
|
||||||
<Col md="4" lg="4" sm="4" xs="5" className="position-relative">
|
<Col md="4" lg="4" sm="4" xs="5" className="position-relative">
|
||||||
<SelectDate
|
<DateTimePicker
|
||||||
onDateChange={this.props.handleTimeFromInput}
|
inputWidth={'100%'}
|
||||||
|
disabledDate={this.disabledStartDate}
|
||||||
value={stateAndValues.time_from}
|
value={stateAndValues.time_from}
|
||||||
locale={lang}
|
onChange={this.props.handleTimeFromInput}
|
||||||
|
showHourAndMinute={false}
|
||||||
/>
|
/>
|
||||||
<span className="select-data-icon"><i className="fa fa-calendar-alt"></i></span>
|
<span className="select-data-icon"><i className="fa fa-calendar-alt"></i></span>
|
||||||
</Col>
|
</Col>
|
||||||
<div className="mt-2">-</div>
|
<div className="mt-2">-</div>
|
||||||
<Col md="4" lg="4" sm="4" xs="5" className="position-relative">
|
<Col md="4" lg="4" sm="4" xs="5" className="position-relative">
|
||||||
<SelectDate
|
<DateTimePicker
|
||||||
onDateChange={this.props.handleTimeToInput}
|
inputWidth={'100%'}
|
||||||
|
disabledDate={this.disabledEndDate}
|
||||||
value={stateAndValues.time_to}
|
value={stateAndValues.time_to}
|
||||||
locale={lang}
|
onChange={this.props.handleTimeToInput}
|
||||||
|
showHourAndMinute={false}
|
||||||
/>
|
/>
|
||||||
<span className="select-data-icon"><i className="fa fa-calendar-alt"></i></span>
|
<span className="select-data-icon"><i className="fa fa-calendar-alt"></i></span>
|
||||||
</Col>
|
</Col>
|
||||||
|
@@ -30,8 +30,8 @@ class SearchViewPanel extends React.Component {
|
|||||||
search_ftypes: search_ftypes,
|
search_ftypes: search_ftypes,
|
||||||
fileTypeItemsStatus: [false, false, false, false, false, false, false],
|
fileTypeItemsStatus: [false, false, false, false, false, false, false],
|
||||||
input_fexts: '',
|
input_fexts: '',
|
||||||
time_from: '',
|
time_from: null,
|
||||||
time_to: '',
|
time_to: null,
|
||||||
size_from: '',
|
size_from: '',
|
||||||
size_to: '',
|
size_to: '',
|
||||||
// search result
|
// search result
|
||||||
@@ -81,8 +81,9 @@ class SearchViewPanel extends React.Component {
|
|||||||
if (this.state.search_ftypes) {params.search_ftypes = this.state.search_ftypes;}
|
if (this.state.search_ftypes) {params.search_ftypes = this.state.search_ftypes;}
|
||||||
if (this.state.per_page) {params.per_page = this.state.per_page;}
|
if (this.state.per_page) {params.per_page = this.state.per_page;}
|
||||||
if (this.state.input_fexts) {params.input_fexts = this.state.input_fexts;}
|
if (this.state.input_fexts) {params.input_fexts = this.state.input_fexts;}
|
||||||
if (this.state.time_from) {params.time_from = moment(this.state.time_from).valueOf() / 1000;}
|
const { time_from, time_to } = this.state;
|
||||||
if (this.state.time_to) {params.time_to = moment(this.state.time_to).valueOf() / 1000;}
|
if (time_from) {params.time_from = parseInt(time_from.valueOf() / 1000);}
|
||||||
|
if (time_to) {params.time_to = parseInt(time_to.valueOf() / 1000);}
|
||||||
if (this.state.size_from) {params.size_from = this.state.size_from * 1000 *1000;}
|
if (this.state.size_from) {params.size_from = this.state.size_from * 1000 *1000;}
|
||||||
if (this.state.size_to) {params.size_to = this.state.size_to * 1000 * 1000;}
|
if (this.state.size_to) {params.size_to = this.state.size_to * 1000 * 1000;}
|
||||||
if (ftype.length !== 0) {params.ftype = ftype;}
|
if (ftype.length !== 0) {params.ftype = ftype;}
|
||||||
@@ -90,10 +91,6 @@ class SearchViewPanel extends React.Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
handleSubmit = () => {
|
handleSubmit = () => {
|
||||||
if (this.compareNumber(this.state.time_from, this.state.time_to)) {
|
|
||||||
this.setState({ errorDateMsg: gettext('Start date should be earlier than end date.') });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.compareNumber(this.state.size_from, this.state.size_to)) {
|
if (this.compareNumber(this.state.size_from, this.state.size_to)) {
|
||||||
this.setState({ errorSizeMsg: gettext('Invalid file size range.') });
|
this.setState({ errorSizeMsg: gettext('Invalid file size range.') });
|
||||||
return;
|
return;
|
||||||
@@ -138,8 +135,8 @@ class SearchViewPanel extends React.Component {
|
|||||||
search_ftypes: search_ftypes,
|
search_ftypes: search_ftypes,
|
||||||
fileTypeItemsStatus: [false, false, false, false, false, false, false],
|
fileTypeItemsStatus: [false, false, false, false, false, false, false],
|
||||||
input_fexts: '',
|
input_fexts: '',
|
||||||
time_from: '',
|
time_from: null,
|
||||||
time_to: '',
|
time_to: null,
|
||||||
size_from: '',
|
size_from: '',
|
||||||
size_to: '',
|
size_to: '',
|
||||||
errorMsg: '',
|
errorMsg: '',
|
||||||
@@ -258,12 +255,14 @@ class SearchViewPanel extends React.Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
handleTimeFromInput = (value) => {
|
handleTimeFromInput = (value) => {
|
||||||
this.setState({ time_from: value });
|
// set the time to be '00:00:00'
|
||||||
|
this.setState({time_from: value ? value.hours(0).minutes(0).seconds(0) : value});
|
||||||
if (this.state.errorDateMsg) this.setState({ errorDateMsg: '' });
|
if (this.state.errorDateMsg) this.setState({ errorDateMsg: '' });
|
||||||
};
|
};
|
||||||
|
|
||||||
handleTimeToInput = (value) => {
|
handleTimeToInput = (value) => {
|
||||||
this.setState({ time_to: value });
|
// set the time to be '23:59:59'
|
||||||
|
this.setState({time_to: value ? value.hours(23).minutes(59).seconds(59) : value});
|
||||||
if (this.state.errorDateMsg) this.setState({ errorDateMsg: '' });
|
if (this.state.errorDateMsg) this.setState({ errorDateMsg: '' });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user