diff --git a/frontend/config/webpack.entry.js b/frontend/config/webpack.entry.js
index 2da3a06f722..9831b0908bb 100644
--- a/frontend/config/webpack.entry.js
+++ b/frontend/config/webpack.entry.js
@@ -40,7 +40,6 @@ const entryFiles = {
repoFolderTrash: '/repo-folder-trash.js',
orgAdmin: '/pages/org-admin',
sysAdmin: '/pages/sys-admin',
- search: '/pages/search',
uploadLink: '/pages/upload-link',
subscription: '/subscription.js',
institutionAdmin: '/pages/institution-admin/index.js'
diff --git a/frontend/src/components/search/search.js b/frontend/src/components/search/search.js
index 57f91b58b07..0c388d16ed1 100644
--- a/frontend/src/components/search/search.js
+++ b/frontend/src/components/search/search.js
@@ -5,7 +5,7 @@ import classnames from 'classnames';
import MediaQuery from 'react-responsive';
import { seafileAPI } from '../../utils/seafile-api';
import searchAPI from '../../utils/search-api';
-import { gettext, siteRoot } from '../../utils/constants';
+import { gettext } from '../../utils/constants';
import SearchResultItem from './search-result-item';
import SearchResultLibrary from './search-result-library';
import { Utils } from '../../utils/utils';
@@ -13,7 +13,6 @@ import toaster from '../toast';
import Loading from '../loading';
import { SEARCH_MASK, SEARCH_CONTAINER } from '../../constants/zIndexes';
import { PRIVATE_FILE_TYPE } from '../../constants';
-import Icon from '../icon';
const propTypes = {
repoID: PropTypes.string,
@@ -35,7 +34,6 @@ class Search extends Component {
constructor(props) {
super(props);
- this.baseSearchPageURL = `${siteRoot}search/`;
this.state = {
width: 'default',
value: '',
@@ -44,13 +42,11 @@ class Search extends Component {
highlightIndex: 0,
page: 0,
isLoading: false,
- hasMore: false,
isMaskShow: false,
showRecent: true,
isResultGotten: false,
isCloseShow: false,
isSearchInputShow: false, // for mobile
- searchPageUrl: this.baseSearchPageURL,
searchTypesMax: 0,
highlightSearchTypesIndex: 0,
};
@@ -367,7 +363,6 @@ class Search extends Component {
inputValue: newValue,
isLoading: false,
highlightIndex: 0,
- // resultItems: [],
isResultGotten: false,
}, () => {
if (!isInRepo && trimmedValue !== '') {
@@ -392,7 +387,6 @@ class Search extends Component {
this.setState({
resultItems: results,
isLoading: false,
- hasMore: false,
});
}).catch(error => {
// eslint-disable-next-line no-console
@@ -428,7 +422,6 @@ class Search extends Component {
isResultGotten: true,
page: page + 1,
isLoading: false,
- hasMore: res.data.has_more,
});
} else {
this.setState({
@@ -436,7 +429,6 @@ class Search extends Component {
resultItems: [],
isLoading: false,
isResultGotten: true,
- hasMore: res.data.has_more,
});
}
}).catch(error => {
@@ -450,7 +442,6 @@ class Search extends Component {
};
onNormalSearch = (queryData, cancelToken, page) => {
- this.updateSearchPageURL(queryData);
queryData['per_page'] = PER_PAGE;
queryData['page'] = page;
seafileAPI.searchFiles(queryData, cancelToken).then(res => {
@@ -461,7 +452,6 @@ class Search extends Component {
isResultGotten: true,
isLoading: false,
page: page + 1,
- hasMore: res.data.has_more,
});
return;
}
@@ -470,7 +460,6 @@ class Search extends Component {
resultItems: [],
isLoading: false,
isResultGotten: true,
- hasMore: res.data.has_more,
});
}).catch(error => {
/* eslint-disable */
@@ -479,14 +468,6 @@ class Search extends Component {
});
};
- updateSearchPageURL(queryData) {
- let params = '';
- for (let key in queryData) {
- params += key + '=' + encodeURIComponent(queryData[key]) + '&';
- }
- this.setState({searchPageUrl: `${this.baseSearchPageURL}?${params.substring(0, params.length - 1)}`});
- }
-
formatResultItems(data) {
let items = [];
for (let i = 0; i < data.length; i++) {
@@ -681,7 +662,7 @@ class Search extends Component {
};
renderResults = (resultItems, isVisited) => {
- const { highlightIndex, hasMore, searchPageUrl } = this.state;
+ const { highlightIndex } = this.state;
const results = (
<>
@@ -700,12 +681,6 @@ class Search extends Component {
);
})}
- {(!this.props.isPublic && hasMore) &&
-
- }
>
);
diff --git a/frontend/src/css/search.css b/frontend/src/css/search.css
index b1801750044..27e19608f21 100644
--- a/frontend/src/css/search.css
+++ b/frontend/src/css/search.css
@@ -451,18 +451,3 @@
font-size: 14px;
margin-bottom: 10px;
}
-
-.search-result-container .more-search-result {
- margin-top: -4px;
- height: 40px;
-}
-
-.search-result-container .more-search-result-icon {
- width: 1rem;
- color: #ec8000;
- margin: 0 10px;
-}
-
-.search-result-container .more-search-result-text {
- font-size: .875rem;
-}
diff --git a/frontend/src/pages/search/advanced-search.js b/frontend/src/pages/search/advanced-search.js
deleted file mode 100644
index 52fd3b41baf..00000000000
--- a/frontend/src/pages/search/advanced-search.js
+++ /dev/null
@@ -1,291 +0,0 @@
-import React, { Fragment } from 'react';
-import PropTypes from 'prop-types';
-import MediaQuery from 'react-responsive';
-import dayjs from 'dayjs';
-import { Button, Col, Collapse, CustomInput, FormGroup, Input, Label, Row, InputGroupAddon, InputGroup } from 'reactstrap';
-import { gettext } from '../../utils/constants';
-import DateTimePicker from '../../components/date-and-time-picker';
-
-const { repo_name, search_repo } = window.search.pageOptions;
-
-class AdvancedSearch extends React.Component {
-
- constructor(props) {
- super(props);
- }
-
- getFileTypesList = (fileTypes) => {
- const fileTypeItems = [gettext('Text'), gettext('Document'), gettext('Image'), gettext('Video'), gettext('Audio'), 'PDF', 'Markdown'];
- let ftype = [];
- for (let i = 0, len = fileTypes.length; i < len; i++) {
- if (fileTypes[i]) {
- ftype.push(fileTypeItems[i]);
- }
- }
- return ftype;
- };
-
- disabledStartDate = (startValue) => {
- if (!startValue) {
- return false;
- }
-
- const isAfterToday = startValue.isAfter(dayjs(), '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(dayjs(), '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;
-
- if (stateAndValues.isShowSearchFilter) {
- const { size_from, size_to, time_from, time_to, search_repo, fileTypeItemsStatus } = stateAndValues;
- const fileTypes = this.getFileTypesList(fileTypeItemsStatus);
- const typesLength = fileTypes.length;
- return (
-
- {search_repo && {gettext('Libraries')}{': '}{search_repo == 'all' ? gettext('All') : repo_name}}
- {typesLength > 0 &&
- {gettext('File Types')}{': '}
- {fileTypes.map((type, index) => {
- return {type}{index !== (typesLength - 1) && ','}{' '};
- })}
-
- }
- {(time_from && time_to) &&
- {gettext('Last Update')}{': '}{time_from.format('YYYY-MM-DD')}{' '}{gettext('to')}{' '}{time_to.format('YYYY-MM-DD')}
- }
- {(size_from && size_to) &&
- {gettext('Size')}{': '}{size_from}{'MB - '}{size_to}{'MB'}
- }
-
- );
- }
- else {
- return (
-
- );
- }
- }
-}
-
-const advancedSearchPropTypes = {
- openFileTypeCollapse: PropTypes.func.isRequired,
- closeFileTypeCollapse: PropTypes.func.isRequired,
- handlerFileTypes: PropTypes.func.isRequired,
- handlerFileTypesInput: PropTypes.func.isRequired,
- handleSubmit: PropTypes.func.isRequired,
- handleReset: PropTypes.func.isRequired,
- handlerRepo: PropTypes.func.isRequired,
- handleKeyDown: PropTypes.func.isRequired,
- handleTimeFromInput: PropTypes.func.isRequired,
- handleTimeToInput: PropTypes.func.isRequired,
- handleSizeFromInput: PropTypes.func.isRequired,
- handleSizeToInput: PropTypes.func.isRequired,
- stateAndValues: PropTypes.object.isRequired,
-};
-
-AdvancedSearch.propTypes = advancedSearchPropTypes;
-
-export default AdvancedSearch;
diff --git a/frontend/src/pages/search/index.js b/frontend/src/pages/search/index.js
deleted file mode 100644
index b1ab402eb5b..00000000000
--- a/frontend/src/pages/search/index.js
+++ /dev/null
@@ -1,42 +0,0 @@
-import React from 'react';
-import ReactDom from 'react-dom';
-import CommonToolbar from '../../components/toolbar/common-toolbar';
-import Logo from '../../components/logo';
-import SearchViewPanel from './main-panel';
-import { siteRoot } from '../../utils/constants';
-import { Utils } from '../../utils/utils';
-
-import '../../css/layout.css';
-import '../../css/toolbar.css';
-import '../../css/search.css';
-
-class SearchView extends React.Component {
-
- constructor(props) {
- super(props);
- }
-
- onSearchedClick = (selectedItem) => {
- let url = selectedItem.is_dir ?
- siteRoot + 'library/' + selectedItem.repo_id + '/' + selectedItem.repo_name + selectedItem.path :
- siteRoot + 'lib/' + selectedItem.repo_id + '/file' + Utils.encodePath(selectedItem.path);
- let newWindow = window.open('about:blank');
- newWindow.location.href = url;
- };
-
- render() {
- return (
-
- );
- }
-}
-
-ReactDom.render(, document.getElementById('wrapper'));
diff --git a/frontend/src/pages/search/main-panel.js b/frontend/src/pages/search/main-panel.js
deleted file mode 100644
index 5afbead5bfe..00000000000
--- a/frontend/src/pages/search/main-panel.js
+++ /dev/null
@@ -1,351 +0,0 @@
-import React from 'react';
-import deepCopy from 'deep-copy';
-import { gettext } from '../../utils/constants';
-import { seafileAPI } from '../../utils/seafile-api';
-import SearchResults from './search-results';
-import AdvancedSearch from './advanced-search';
-import toaster from '../../components/toast';
-import Loading from '../../components/loading';
-
-import '../../css/search.css';
-
-const { q, search_repo, search_ftypes } = window.search.pageOptions;
-
-class SearchViewPanel extends React.Component {
-
- constructor(props) {
- super(props);
- this.stateHistory = null;
- this.state = {
- isCollapseOpen: search_repo !== 'all',
- isFileTypeCollapseOpen: false,
- isResultGot: false,
- isLoading: true,
- isAllRepoCheck: search_repo === 'all',
- isShowSearchFilter: false,
- // advanced search index
- q: q.trim(),
- search_repo: search_repo,
- search_ftypes: search_ftypes,
- fileTypeItemsStatus: [false, false, false, false, false, false, false],
- input_fexts: '',
- time_from: null,
- time_to: null,
- size_from: '',
- size_to: '',
- // search result
- hasMore: false,
- resultItems: [],
- page: 1,
- per_page: 20,
- errorMsg: '',
- errorDateMsg: '',
- errorSizeMsg: '',
- };
- }
-
- getSearchResults(params) {
- this.setState({
- isLoading: true,
- isResultGot: false,
- });
- this.onNormalSearch(params);
- }
-
- onNormalSearch = (params) => {
- const stateHistory = deepCopy(this.state);
- seafileAPI.searchFiles(params, null).then(res => {
- const { results, has_more, total } = res.data;
- this.setState({
- isLoading: false,
- isResultGot: true,
- resultItems: results,
- hasMore: has_more,
- total: total,
- page: params.page,
- isShowSearchFilter: true,
- });
- this.stateHistory = stateHistory;
- this.stateHistory.resultItems = results;
- this.stateHistory.hasMore = has_more;
- this.stateHistory.page = params.page;
- }).catch((error) => {
- this.setState({ isLoading: false });
- if (error.response) {
- toaster.danger(error.response.data.detail || error.response.data.error_msg || gettext('Error'), { duration: 3 });
- } else {
- toaster.danger(gettext('Please check the network.'), { duration: 3 });
- }
- });
- };
-
- handleSearchParams = (page) => {
- let params = { q: this.state.q.trim(), page: page };
- const ftype = this.getFileTypesList();
- if (this.state.search_repo) {params.search_repo = this.state.search_repo;}
- 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;}
- 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;}
- return params;
- };
-
- handleSubmit = () => {
- if (this.compareNumber(this.state.size_from, this.state.size_to)) {
- this.setState({ errorSizeMsg: gettext('Invalid file size range.') });
- return;
- }
- if (this.getValueLength(this.state.q.trim()) < 3) {
- if (this.state.q.trim().length === 0) {
- this.setState({ errorMsg: gettext('It is required.') });
- } else {
- this.setState({ errorMsg: gettext('Required at least three letters.') });
- }
- if (this.state.isLoading) {
- this.setState({ isLoading: false });
- }
- } else {
- const params = this.handleSearchParams(1);
- this.getSearchResults(params);
- }
- if (this.state.isCollapseOpen) this.setState({ isCollapseOpen: false });
- };
-
- compareNumber = (num1, num2) => {
- if (!num1 || !num2) return false;
- // eslint-disable-next-line
- if (parseInt(num1.replace(/\-/g, '')) >= parseInt(num2.replace(/\-/g, ''))) {
- return true;
- } else {
- return false;
- }
- };
-
- showSearchFilter = () => {
- this.setState({ isShowSearchFilter: true });
- };
-
- hideSearchFilter = () => {
- this.setState({ isShowSearchFilter: false });
- };
-
- handleReset = () => {
- this.setState({
- q: q.trim(),
- search_repo: search_repo,
- search_ftypes: search_ftypes,
- fileTypeItemsStatus: [false, false, false, false, false, false, false],
- input_fexts: '',
- time_from: null,
- time_to: null,
- size_from: '',
- size_to: '',
- errorMsg: '',
- errorDateMsg: '',
- errorSizeMsg: '',
- });
- };
-
- handlePrevious = (e) => {
- e.preventDefault();
- if (this.stateHistory && this.state.page > 1) {
- this.setState(this.stateHistory, () => {
- const params = this.handleSearchParams(this.state.page - 1);
- this.getSearchResults(params);
- });
- } else {
- toaster.danger(gettext('Error'), { duration: 3 });
- }
- };
-
- handleNext = (e) => {
- e.preventDefault();
- if (this.stateHistory && this.state.hasMore) {
- this.setState(this.stateHistory, () => {
- const params = this.handleSearchParams(this.state.page + 1);
- this.getSearchResults(params);
- });
- } else {
- toaster.danger(gettext('Error'), { duration: 3 });
- }
- };
-
- getValueLength(str) {
- let code = 0;
- let len = 0;
- for (let i = 0, length = str.length; i < length; i++) {
- code = str.charCodeAt(i);
- if (code === 10) { // solve enter problem
- len += 2;
- } else if (code < 0x007f) {
- len += 1;
- } else if (code >= 0x0080 && code <= 0x07ff) {
- len += 2;
- } else if (code >= 0x0800 && code <= 0xffff) {
- len += 3;
- }
- }
- return len;
- }
-
- toggleCollapse = () => {
- this.setState({ isCollapseOpen: !this.state.isCollapseOpen });
- this.hideSearchFilter();
- };
-
- openFileTypeCollapse = () => {
- this.setState({
- isFileTypeCollapseOpen: true,
- search_ftypes: 'custom',
- });
- };
-
- closeFileTypeCollapse = () => {
- this.setState({
- isFileTypeCollapseOpen: false,
- fileTypeItemsStatus: Array(7).fill(false),
- search_ftypes: 'all',
- input_fexts: '',
- });
- };
-
- handleSearchInput = (event) => {
- this.setState({ q: event.target.value });
- if (this.state.errorMsg) this.setState({ errorMsg: '' });
- if (this.state.errorSizeMsg) this.setState({ errorSizeMsg: '' });
- if (this.state.errorDateMsg) this.setState({ errorDateMsg: '' });
- };
-
- handleKeyDown = (e) => {
- if (e.keyCode === 13) {
- e.preventDefault();
- this.handleSubmit();
- }
- };
-
- handlerRepo = (isAll) => {
- if (isAll) {
- this.setState({
- isAllRepoCheck: true,
- search_repo: 'all',
- });
- } else {
- this.setState({
- isAllRepoCheck: false,
- search_repo: search_repo !== 'all' ? search_repo : '',
- });
- }
- };
-
- handlerFileTypes = (i) => {
- let newFileTypeItemsStatus = this.state.fileTypeItemsStatus;
- newFileTypeItemsStatus[i] = !this.state.fileTypeItemsStatus[i];
- this.setState({ fileTypeItemsStatus: newFileTypeItemsStatus });
- };
-
- getFileTypesList = () => {
- const fileTypeItems = ['Text', 'Document', 'Image', 'Video', 'Audio', 'PDF', 'Markdown'];
- let ftype = [];
- for (let i = 0, len = this.state.fileTypeItemsStatus.length; i < len; i++) {
- if (this.state.fileTypeItemsStatus[i]) {
- ftype.push(fileTypeItems[i]);
- }
- }
- return ftype;
- };
-
- handlerFileTypesInput = (event) => {
- this.setState({ input_fexts: event.target.value.trim() });
- };
-
- handleTimeFromInput = (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) => {
- // 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: '' });
- };
-
- handleSizeFromInput = (event) => {
- this.setState({ size_from: event.target.value >= 0 ? event.target.value : 0 });
- if (this.state.errorSizeMsg) this.setState({ errorSizeMsg: '' });
- };
-
- handleSizeToInput = (event) => {
- this.setState({ size_to: event.target.value >= 0 ? event.target.value : 0 });
- if (this.state.errorSizeMsg) this.setState({ errorSizeMsg: '' });
- };
-
- componentDidMount() {
- if (this.state.q) {
- this.handleSubmit();
- } else {
- this.setState({ isLoading: false });
- }
- }
-
- render() {
- let { isCollapseOpen } = this.state;
- return (
-
-
-
-
-
-
-
- {this.state.errorMsg &&
{this.state.errorMsg}
}
-
-
- {this.state.isLoading &&
}
- {(!this.state.isLoading && this.state.isResultGot) &&
-
- }
- {(!this.state.isLoading && this.state.isResultGot) &&
-
- }
-
- );
- }
-}
-
-export default SearchViewPanel;
diff --git a/frontend/src/pages/search/search-results.js b/frontend/src/pages/search/search-results.js
deleted file mode 100644
index b80a804ec94..00000000000
--- a/frontend/src/pages/search/search-results.js
+++ /dev/null
@@ -1,91 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import dayjs from 'dayjs';
-import { Utils } from '../../utils/utils';
-import { siteRoot, gettext } from '../../utils/constants';
-
-class ResultsItem extends React.Component {
-
- constructor(props) {
- super(props);
- }
-
- handlerFileURL = (item) => {
- return item.is_dir ? siteRoot + 'library/' + item.repo_id + '/' + item.repo_name + item.fullpath :
- siteRoot + 'lib/' + item.repo_id + '/file' + Utils.encodePath(item.fullpath);
- };
-
- handlerParentDirPath = (item) => {
- let index = item.is_dir ? item.fullpath.length - item.name.length - 1 : item.fullpath.length - item.name.length;
- return item.fullpath.substring(0, index);
- };
-
- handlerParentDirURL = (item) => {
- return siteRoot + 'library/' + item.repo_id + '/' + item.repo_name + this.handlerParentDirPath(item);
- };
-
- render() {
- let item = this.props.item;
- let linkContent = decodeURI(item.fullpath).substring(1);
- let folderIconUrl = linkContent ? Utils.getFolderIconUrl(false, 192) : Utils.getDefaultLibIconUrl();
- let fileIconUrl = item.is_dir ? folderIconUrl : Utils.getFileIconUrl(item.name);
-
- if (item.thumbnail_url !== '') {
- fileIconUrl = item.thumbnail_url;
- }
-
- return (
-
-
-
-
-
-
- {Utils.bytesToSize(item.size) + ' ' + dayjs(item.last_modified * 1000).format('YYYY-MM-DD')}
-
-
-
-
- );
- }
-}
-
-const resultsItemPropTypes = {
- item: PropTypes.object.isRequired,
-};
-
-ResultsItem.propTypes = resultsItemPropTypes;
-
-class SearchResults extends React.Component {
-
- constructor(props) {
- super(props);
- }
-
- render() {
- const { resultItems, total } = this.props;
- return (
-
-
{total > 0 ? (total + ' ' + (total === 1 ? gettext('result') : gettext('results'))) : gettext('No result')}
-
- {resultItems.map((item, index) => {
- return ;
- })}
-
-
- );
- }
-}
-
-const searchResultsPropTypes = {
- resultItems: PropTypes.array.isRequired,
- total: PropTypes.number.isRequired
-};
-
-SearchResults.propTypes = searchResultsPropTypes;
-
-export default SearchResults;
diff --git a/media/css/jquery-ui.datepicker.min.css b/media/css/jquery-ui.datepicker.min.css
deleted file mode 100644
index ecd290d7e72..00000000000
--- a/media/css/jquery-ui.datepicker.min.css
+++ /dev/null
@@ -1,18 +0,0 @@
-/*! jQuery UI - v1.11.4 - 2015-11-16
-* http://jqueryui.com
-* Includes: core.css, datepicker.css, theme.css
-* added some customed styles in the last, by lj, 2015-11-17
-* Copyright jQuery Foundation and other contributors; Licensed MIT */
-.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:45%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-widget{font-family:Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Verdana,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #aaa;background:#fff;color:#222}.ui-widget-content a{color:#222}.ui-widget-header{border:1px solid #aaa;background:#ccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x;color:#222;font-weight:bold}.ui-widget-header a{color:#222}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #d3d3d3;background:#e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#555}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#555;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #999;background:#dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited{color:#212121;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #aaa;background:#fff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#212121;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fcefa1;background:#fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x;color:#cd0a0a}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#cd0a0a}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#cd0a0a}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_222222_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_222222_256x240.png")}.ui-state-default .ui-icon{background-image:url("images/ui-icons_888888_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url("images/ui-icons_454545_256x240.png")}.ui-state-active .ui-icon{background-image:url("images/ui-icons_454545_256x240.png")}.ui-state-highlight .ui-icon{background-image:url("images/ui-icons_2e83ff_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_cd0a0a_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:4px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:4px}.ui-widget-overlay{background:#aaa;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{margin:-8px 0 0 -8px;padding:8px;background:#aaa;opacity:.3;filter:Alpha(Opacity=30);border-radius:8px}
-/* customed styles*/
-.ui-widget-header { background:#ccc; }
-.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default {
- background: #e6e6e6;
-}
-.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus {
- background:#dadada;
-}
-.ui-datepicker .ui-widget-header .ui-icon {
- background-image:url('../img/ui-icons_444444_256x240.png');
- cursor:pointer;
-}
diff --git a/seahub/search/templates/search_results.html b/seahub/search/templates/search_results.html
deleted file mode 100644
index c47a20836c3..00000000000
--- a/seahub/search/templates/search_results.html
+++ /dev/null
@@ -1,266 +0,0 @@
-{% extends 'base.html' %}
-
-{% load seahub_tags avatar_tags i18n static %}
-
-
-{% block extra_style %}
-
-
-{% endblock %}
-
-{% block main_content %}
-
-
-
-
-
- {% if error %}
-
{{error_msg}}
- {% else %}
-{% if not results %}
-
{% trans 'No result found' %}
-{% else %}
-
{% blocktrans count counter=total %}{{ total }} result{% plural %}{{ total }} results{% endblocktrans%}
-
- {% for file in results %}
- {% if file.is_dir %}
- -
-
- {% else %}
-
-
-
-
-
- {% endif %}
-
- {% if file.is_dir %}
-
{{ file.name }}
- {% else %}
-
{{ file.name }}
- {% endif %}
-
- {% if file.parent_dir == '/' %}
-
{{ file.repo.name }}/
- {% else %}
-
{{ file.repo.name }}{{ file.parent_dir }}
- {% endif %}
-
- {% if file.is_dir %}
-
{{ file.last_modified|translate_seahub_time }}
- {% else %}
-
{{ file.size|filesizeformat }} {{ file.last_modified|translate_seahub_time }}
- {% endif %}
- {% if file.content_highlight %}
-
{{ file.content_highlight|safe }}
- {% endif %}
-
-
- {% endfor %}
-
- {% if total > per_page %}
-
- {% endif %}
-{% endif %}
-{% endif %}
-
-
-
-{% endblock %}
-
-{% block extra_script %}
-
-
-{% endblock %}
diff --git a/seahub/search/templates/search_results_react.html b/seahub/search/templates/search_results_react.html
deleted file mode 100644
index 17f4da2aec1..00000000000
--- a/seahub/search/templates/search_results_react.html
+++ /dev/null
@@ -1,20 +0,0 @@
-{% extends "base_for_react.html" %}
-{% load render_bundle from webpack_loader %}
-
-{% block extra_style %}
- {% render_bundle 'search' 'css' %}
-{% endblock %}
-
-{% block extra_script %}
-
- {% render_bundle 'search' 'js' %}
-{% endblock %}
diff --git a/seahub/search/utils.py b/seahub/search/utils.py
index 1dfd27af1fb..9c08feea4c6 100644
--- a/seahub/search/utils.py
+++ b/seahub/search/utils.py
@@ -238,25 +238,6 @@ def ai_search_wikis(params):
resp = requests.post(url, json=params, headers=headers)
return resp
-
-def is_valid_date_type(data):
- try:
- data = int(data)
- except:
- return False
- else:
- return True
-
-def is_valid_size_type(data):
- try:
- data = int(data)
- if data < 0:
- raise
- except:
- return False
- else:
- return True
-
SEARCH_REPOS_LIMIT = 200
RELATED_REPOS_PREFIX = 'RELATED_REPOS_'
RELATED_REPOS_CACHE_TIMEOUT = 2 * 60 * 60
diff --git a/seahub/search/views.py b/seahub/search/views.py
deleted file mode 100644
index 75338de19f7..00000000000
--- a/seahub/search/views.py
+++ /dev/null
@@ -1,305 +0,0 @@
-# Copyright (c) 2012-2016 Seafile Ltd.
-import os
-import logging
-
-from django.urls import reverse
-from django.http import HttpResponseRedirect, Http404
-from django.shortcuts import render
-
-from django.utils.translation import gettext as _
-
-from seaserv import seafile_api, ccnet_api
-
-from seahub.auth.decorators import login_required
-from seahub.contacts.models import Contact
-from seahub.profile.models import Profile
-from seahub.utils import is_org_context
-from seahub.utils.repo import is_valid_repo_id_format
-from seahub.views import check_folder_permission
-from seahub.settings import THUMBNAIL_SIZE_FOR_GRID
-from seahub.search.utils import search_files, get_search_repos_map, \
- SEARCH_FILEEXT, is_valid_date_type, is_valid_size_type
-
-logger = logging.getLogger(__name__)
-
-@login_required
-def search(request):
-
- custom_search = False
- invalid_argument = False
- need_return_custom_search = False
- invalid_info = {
- 'error': True,
- 'error_msg': _('Invalid argument.'),
- }
-
- # argument check
- username = request.user.username
- org_id = request.user.org.org_id if is_org_context(request) else None
- keyword = request.GET.get('q', None)
-
- try:
- current_page = int(request.GET.get('page', '1'))
- per_page = int(request.GET.get('per_page', '25'))
- except ValueError:
- current_page = 1
- per_page = 25
-
- start = (current_page - 1) * per_page
- size = per_page
- if start < 0 or size < 0:
- invalid_argument = True
-
- search_repo = request.GET.get('search_repo', 'all') # val: 'all' or 'repo_id'
- search_repo = search_repo.lower()
- if not is_valid_repo_id_format(search_repo) and search_repo != 'all':
- invalid_argument = True
-
- search_path = request.GET.get('search_path', None)
- if search_path is not None and search_path[0] != '/':
- search_path = "/{0}".format(search_path)
-
- search_ftypes = request.GET.get('search_ftypes', 'all') # val: 'all' or 'custom'
- search_ftypes = search_ftypes.lower()
- if search_ftypes not in ('all', 'custom'):
- invalid_argument = True
-
- time_from = request.GET.get('time_from', '')
- time_to = request.GET.get('time_to', '')
- size_from = request.GET.get('size_from', '')
- size_to = request.GET.get('size_to', '')
-
- date_from = request.GET.get('date_from', '')
- date_to = request.GET.get('date_to', '')
- size_from_mb = request.GET.get('size_from_mb', '')
- size_to_mb = request.GET.get('size_to_mb', '')
-
- if time_from:
- if not is_valid_date_type(time_from) and not invalid_argument:
- need_return_custom_search = True
- invalid_argument = True
- invalid_info['error_msg'] = _('Invalid date.')
- else:
- time_from = None
-
- if time_to:
- if not is_valid_date_type(time_to) and not invalid_argument:
- need_return_custom_search = True
- invalid_argument = True
- invalid_info['error_msg'] = _('Invalid date.')
- else:
- time_to = None
-
- if size_from:
- if not is_valid_size_type(size_from) and not invalid_argument:
- need_return_custom_search = True
- invalid_argument = True
- invalid_info['error_msg'] = _('Invalid file size.')
- else:
- size_from = None
-
- if size_to:
- if not is_valid_size_type(size_to) and not invalid_argument:
- need_return_custom_search = True
- invalid_argument = True
- invalid_info['error_msg'] = _('Invalid file size.')
- else:
- size_to = None
-
- if size_to and size_from and size_to < size_from and not invalid_argument:
- invalid_argument = True
- need_return_custom_search = True
- invalid_info['error_msg'] = _('Invalid file size range.')
-
- if time_to and time_from and time_to < time_from and not invalid_argument:
- invalid_argument = True
- need_return_custom_search = True
- invalid_info['error_msg'] = _('Invalid date range.')
-
- time_range = (time_from, time_to)
- size_range = (size_from, size_to)
- suffixes = None
- custom_ftypes = request.GET.getlist('ftype') # types like 'Image', 'Video'... same in utils/file_types.py
- input_fileexts = request.GET.get('input_fexts', '') # file extension input by the user
- if search_ftypes == 'custom':
- suffixes = []
- if len(custom_ftypes) > 0:
- for ftp in custom_ftypes:
- if ftp in SEARCH_FILEEXT:
- for ext in SEARCH_FILEEXT[ftp]:
- suffixes.append(ext)
-
- if input_fileexts:
- input_fexts = input_fileexts.split(',')
- for i_ext in input_fexts:
- i_ext = i_ext.strip()
- if i_ext:
- suffixes.append(i_ext)
-
- range_args = [time_from, time_to, size_from, size_to]
- if search_repo != 'all' or search_ftypes == 'custom' or any(e for e in range_args):
- custom_search = True
-
- if invalid_argument:
- if need_return_custom_search:
- invalid_info['keyword'] = keyword
- invalid_info['search_repo'] = search_repo
- invalid_info['search_ftypes'] = search_ftypes
- invalid_info['custom_ftypes'] = custom_ftypes
- invalid_info['input_fileexts'] = input_fileexts
- invalid_info['custom_search'] = custom_search
- invalid_info['date_from'] = date_from
- invalid_info['date_to'] = date_to
- invalid_info['size_from_mb'] = size_from_mb
- invalid_info['size_to_mb'] = size_to_mb
- return render(request, 'search_results.html', invalid_info)
-
- repo_id_map = {}
- # check recourse and permissin when search in a single repo
- if is_valid_repo_id_format(search_repo):
- repo_id = search_repo
- repo = seafile_api.get_repo(repo_id)
- # recourse check
- if not repo:
- data = {
- 'error': True,
- 'error_msg': _('Library %s not found.') % repo_id
- }
- return render(request, 'search_results.html', data)
-
- # permission check
- if not check_folder_permission(request, repo_id, '/'):
- data = {
- 'error': True,
- 'error_msg': _('Permission denied.')
- }
- return render(request, 'search_results.html', data)
- map_id = repo.origin_repo_id if repo.origin_repo_id else repo_id
- repo_id_map[map_id] = repo
- else:
- shared_from = request.GET.get('shared_from', None)
- not_shared_from = request.GET.get('not_shared_from', None)
- repo_id_map, repo_type_map = get_search_repos_map(search_repo,
- username, org_id, shared_from, not_shared_from)
-
- obj_desc = {
- 'suffixes': suffixes,
- 'time_range': time_range,
- 'size_range': size_range
- }
- # search file
- try:
- if keyword:
- results, total = search_files(repo_id_map, search_path, keyword, obj_desc, start, size, org_id)
- else:
- results, total, keyword = [], 0, ''
- except Exception as e:
- logger.error(e)
- data = {
- 'error': True,
- 'error_msg': _('Internal Server Error')
- }
- return render(request, 'search_results.html', data)
-
- has_more = True if total > current_page * per_page else False
- for r in results:
- r['parent_dir'] = os.path.dirname(r['fullpath'].rstrip('/'))
-
- response_dict = {
- 'repo': repo if is_valid_repo_id_format(search_repo) else None,
- 'keyword': keyword,
- 'results': results,
- 'total': total,
- 'has_more': has_more,
- 'current_page': current_page,
- 'prev_page': current_page - 1,
- 'next_page': current_page + 1,
- 'per_page': per_page,
- 'search_repo': search_repo,
- 'search_ftypes': search_ftypes,
- 'custom_ftypes': custom_ftypes,
- 'input_fileexts': input_fileexts,
- 'error': False,
- 'thumbnail_size': THUMBNAIL_SIZE_FOR_GRID,
- 'date_from': date_from,
- 'date_to': date_to,
- 'size_from_mb': size_from_mb,
- 'size_to_mb': size_to_mb,
- 'custom_search': custom_search
- }
-
- # Whether use new index page
- use_new_page = True
- if request.GET.get('_old', None):
- use_new_page = False
-
- if use_new_page:
- return render(request, 'search_results_react.html', response_dict)
-
- return render(request, 'search_results.html', response_dict)
-
-@login_required
-def pubuser_search(request):
- can_search = False
- if is_org_context(request):
- can_search = True
- elif request.cloud_mode:
- # Users are not allowed to search public user when in cloud mode.
- can_search = False
- else:
- can_search = True
-
- if can_search is False:
- raise Http404
-
- email_or_nickname = request.GET.get('search', '')
- if not email_or_nickname:
- return HttpResponseRedirect(reverse('pubuser'))
-
- # Get user's contacts, used in show "add to contacts" button.
- username = request.user.username
- contacts = Contact.objects.get_contacts_by_user(username)
- contact_emails = [request.user.username]
- for c in contacts:
- contact_emails.append(c.contact_email)
-
- search_result = []
- # search by username
- if is_org_context(request):
- url_prefix = request.user.org.url_prefix
- org_users = ccnet_api.get_org_users_by_url_prefix(url_prefix, -1, -1)
- users = []
- for u in org_users:
- if email_or_nickname in u.email:
- users.append(u)
- else:
- users = ccnet_api.search_emailusers(email_or_nickname, -1, -1)
- for u in users:
- can_be_contact = True if u.email not in contact_emails else False
- search_result.append({'email': u.email,
- 'can_be_contact': can_be_contact})
-
- # search by nickname
- if is_org_context(request):
- url_prefix = request.user.org.url_prefix
- org_users = ccnet_api.get_org_users_by_url_prefix(url_prefix, -1, -1)
- profile_all = Profile.objects.filter(user__in=[u.email for u in org_users]).values('user', 'nickname')
- else:
- profile_all = Profile.objects.all().values('user', 'nickname')
- for p in profile_all:
- if email_or_nickname in p['nickname']:
- can_be_contact = True if p['user'] not in contact_emails else False
- search_result.append({'email': p['user'],
- 'can_be_contact': can_be_contact})
-
- uniq_usernames = []
- for res in search_result:
- if res['email'] not in uniq_usernames:
- uniq_usernames.append(res['email'])
- else:
- search_result.remove(res)
-
- return render(request, 'pubuser.html', {
- 'search': email_or_nickname,
- 'users': search_result,
- })
diff --git a/seahub/urls.py b/seahub/urls.py
index 98694a9f1b6..c9c72912883 100644
--- a/seahub/urls.py
+++ b/seahub/urls.py
@@ -910,14 +910,6 @@
re_path(r'^demo/', demo),
]
-from seahub.utils import HAS_FILE_SEARCH, HAS_FILE_SEASEARCH
-if HAS_FILE_SEARCH or HAS_FILE_SEASEARCH:
- from seahub.search.views import search, pubuser_search
- urlpatterns += [
- path('search/', search, name='search'),
- path('pubinfo/users/search/', pubuser_search, name='pubuser_search'),
- ]
-
from seahub.utils import is_pro_version
if is_pro_version():
urlpatterns += [