mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-02 07:27:04 +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
|
||||
};
|
||||
|
||||
const FORMAT = 'YYYY-MM-DD HH:mm';
|
||||
|
||||
class Picker extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
@@ -24,7 +22,7 @@ class Picker extends React.Component {
|
||||
this.calendarContainerRef = React.createRef();
|
||||
this.inputRef = React.createRef();
|
||||
this.state = {
|
||||
isOpen: true
|
||||
isOpen: false
|
||||
};
|
||||
}
|
||||
|
||||
@@ -64,12 +62,20 @@ class Picker extends React.Component {
|
||||
|
||||
render() {
|
||||
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
|
||||
defaultValue={this.defaultCalendarValue}
|
||||
disabledDate={props.disabledDate}
|
||||
format={FORMAT}
|
||||
locale={translateCalendar()}
|
||||
showHourAndMinute={true}
|
||||
showHourAndMinute={showHourAndMinute}
|
||||
/>);
|
||||
return (
|
||||
<DatePicker
|
||||
|
@@ -1,9 +1,10 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
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 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;
|
||||
|
||||
@@ -24,6 +25,34 @@ class AdvancedSearch extends React.Component {
|
||||
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() {
|
||||
const { stateAndValues } = this.props;
|
||||
const { errorDateMsg, errorSizeMsg } = stateAndValues;
|
||||
@@ -43,7 +72,7 @@ class AdvancedSearch extends React.Component {
|
||||
</span>
|
||||
}
|
||||
{(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) &&
|
||||
<span className="mr-4">{gettext('Size')}{': '}{size_from}{'MB - '}{size_to}{'MB'}</span>
|
||||
@@ -168,19 +197,23 @@ class AdvancedSearch extends React.Component {
|
||||
<Row>
|
||||
<Col md="2" lg="2" className="mt-2">{gettext('Last Update')}{': '}</Col>
|
||||
<Col md="4" lg="4" sm="4" xs="5" className="position-relative">
|
||||
<SelectDate
|
||||
onDateChange={this.props.handleTimeFromInput}
|
||||
<DateTimePicker
|
||||
inputWidth={'100%'}
|
||||
disabledDate={this.disabledStartDate}
|
||||
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>
|
||||
</Col>
|
||||
<div className="mt-2">-</div>
|
||||
<Col md="4" lg="4" sm="4" xs="5" className="position-relative">
|
||||
<SelectDate
|
||||
onDateChange={this.props.handleTimeToInput}
|
||||
<DateTimePicker
|
||||
inputWidth={'100%'}
|
||||
disabledDate={this.disabledEndDate}
|
||||
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>
|
||||
</Col>
|
||||
|
@@ -30,8 +30,8 @@ class SearchViewPanel extends React.Component {
|
||||
search_ftypes: search_ftypes,
|
||||
fileTypeItemsStatus: [false, false, false, false, false, false, false],
|
||||
input_fexts: '',
|
||||
time_from: '',
|
||||
time_to: '',
|
||||
time_from: null,
|
||||
time_to: null,
|
||||
size_from: '',
|
||||
size_to: '',
|
||||
// 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.per_page) {params.per_page = this.state.per_page;}
|
||||
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;}
|
||||
if (this.state.time_to) {params.time_to = moment(this.state.time_to).valueOf() / 1000;}
|
||||
const { time_from, time_to } = this.state;
|
||||
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_to) {params.size_to = this.state.size_to * 1000 * 1000;}
|
||||
if (ftype.length !== 0) {params.ftype = ftype;}
|
||||
@@ -90,10 +91,6 @@ class SearchViewPanel extends React.Component {
|
||||
};
|
||||
|
||||
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)) {
|
||||
this.setState({ errorSizeMsg: gettext('Invalid file size range.') });
|
||||
return;
|
||||
@@ -138,8 +135,8 @@ class SearchViewPanel extends React.Component {
|
||||
search_ftypes: search_ftypes,
|
||||
fileTypeItemsStatus: [false, false, false, false, false, false, false],
|
||||
input_fexts: '',
|
||||
time_from: '',
|
||||
time_to: '',
|
||||
time_from: null,
|
||||
time_to: null,
|
||||
size_from: '',
|
||||
size_to: '',
|
||||
errorMsg: '',
|
||||
@@ -258,12 +255,14 @@ class SearchViewPanel extends React.Component {
|
||||
};
|
||||
|
||||
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: '' });
|
||||
};
|
||||
|
||||
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: '' });
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user