1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-10 03:11:07 +00:00

improve/add-empty-tip-when-no-file (#6760)

This commit is contained in:
Michael An
2024-09-12 14:03:29 +08:00
committed by GitHub
parent b6ae9eca80
commit 5bebec6aee
9 changed files with 73 additions and 33 deletions

View File

@@ -11,6 +11,8 @@ import ModalPortal from '../../components/modal-portal';
import toaster from '../../components/toast'; import toaster from '../../components/toast';
import CleanTrash from '../../components/dialog/clean-trash'; import CleanTrash from '../../components/dialog/clean-trash';
import Paginator from '../paginator'; import Paginator from '../paginator';
import Loading from '../../components/loading';
import EmptyTip from '../../components/empty-tip';
import '../../css/toolbar.css'; import '../../css/toolbar.css';
import '../../css/search.css'; import '../../css/search.css';
@@ -141,7 +143,7 @@ class TrashDialog extends React.Component {
render() { render() {
const { showTrashDialog, toggleTrashDialog } = this.props; const { showTrashDialog, toggleTrashDialog } = this.props;
const { isCleanTrashDialogOpen, showFolder } = this.state; const { isCleanTrashDialogOpen, showFolder, isLoading, items } = this.state;
const isRepoAdmin = this.props.currentRepoInfo.owner_email === username || this.props.currentRepoInfo.is_admin; const isRepoAdmin = this.props.currentRepoInfo.owner_email === username || this.props.currentRepoInfo.is_admin;
const repoFolderName = this.props.currentRepoInfo.repo_name; const repoFolderName = this.props.currentRepoInfo.repo_name;
const oldTrashUrl = siteRoot + 'repo/' + this.props.repoID + '/trash/'; const oldTrashUrl = siteRoot + 'repo/' + this.props.repoID + '/trash/';
@@ -164,6 +166,11 @@ class TrashDialog extends React.Component {
<div dangerouslySetInnerHTML={{ __html: title }}></div> <div dangerouslySetInnerHTML={{ __html: title }}></div>
</ModalHeader> </ModalHeader>
<ModalBody> <ModalBody>
{isLoading && <Loading />}
{!isLoading && items.length === 0 &&
<EmptyTip text={gettext('No file')} className="m-0" />
}
{!isLoading && items.length > 0 &&
<Content <Content
data={this.state} data={this.state}
repoID={this.props.repoID} repoID={this.props.repoID}
@@ -175,6 +182,7 @@ class TrashDialog extends React.Component {
getListByPage={this.getItems2} getListByPage={this.getItems2}
resetPerPage={this.resetPerPage} resetPerPage={this.resetPerPage}
/> />
}
{isCleanTrashDialogOpen && {isCleanTrashDialogOpen &&
<ModalPortal> <ModalPortal>
<CleanTrash <CleanTrash

View File

@@ -1,6 +1,6 @@
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { siteRoot, username, enableSeadoc, thumbnailDefaultSize, thumbnailSizeForOriginal } from '../../utils/constants'; import { siteRoot, username, enableSeadoc, thumbnailDefaultSize, thumbnailSizeForOriginal, gettext } from '../../utils/constants';
import { Utils } from '../../utils/utils'; import { Utils } from '../../utils/utils';
import { seafileAPI } from '../../utils/seafile-api'; import { seafileAPI } from '../../utils/seafile-api';
import URLDecorator from '../../utils/url-decorator'; import URLDecorator from '../../utils/url-decorator';
@@ -24,6 +24,7 @@ import toaster from '../toast';
import imageAPI from '../../utils/image-api'; import imageAPI from '../../utils/image-api';
import FileAccessLog from '../dialog/file-access-log'; import FileAccessLog from '../dialog/file-access-log';
import { EVENT_BUS_TYPE } from '../common/event-bus-type'; import { EVENT_BUS_TYPE } from '../common/event-bus-type';
import EmptyTip from '../empty-tip';
import '../../css/grid-view.css'; import '../../css/grid-view.css';
@@ -826,16 +827,16 @@ class DirentGridView extends React.Component {
return ( return (
<Fragment> <Fragment>
<ul {direntList.length > 0 ?
className="grid-view" <ul
onClick={this.gridContainerClick} className="grid-view"
onContextMenu={this.onGridContainerContextMenu} onClick={this.gridContainerClick}
onMouseDown={this.onGridContainerMouseDown} onContextMenu={this.onGridContainerContextMenu}
onMouseMove={this.onSelectMouseMove} onMouseDown={this.onGridContainerMouseDown}
ref={this.containerRef} onMouseMove={this.onSelectMouseMove}
> ref={this.containerRef}
{ >
direntList.length !== 0 && direntList.map((dirent, index) => { {direntList.map((dirent, index) => {
return ( return (
<DirentGridItem <DirentGridItem
key={index} key={index}
@@ -854,10 +855,21 @@ class DirentGridView extends React.Component {
selectedDirentList={selectedDirentList} selectedDirentList={selectedDirentList}
/> />
); );
}) })}
} {this.renderSelectionBox()}
{this.renderSelectionBox()} </ul>
</ul> :
<ul
className="grid-view"
onClick={this.gridContainerClick}
onContextMenu={this.onGridContainerContextMenu}
onMouseDown={this.onGridContainerMouseDown}
onMouseMove={this.onSelectMouseMove}
ref={this.containerRef}
>
<EmptyTip text={gettext('No file')} className='w-100' />
</ul>
}
<ContextMenu <ContextMenu
id={GRID_ITEM_CONTEXTMENU_ID} id={GRID_ITEM_CONTEXTMENU_ID}
onMenuItemClick={this.onMenuItemClick} onMenuItemClick={this.onMenuItemClick}

View File

@@ -18,6 +18,7 @@ import ContextMenu from '../context-menu/context-menu';
import { hideMenu, showMenu } from '../context-menu/actions'; import { hideMenu, showMenu } from '../context-menu/actions';
import DirentsDraggedPreview from '../draggable/dirents-dragged-preview'; import DirentsDraggedPreview from '../draggable/dirents-dragged-preview';
import { EVENT_BUS_TYPE } from '../common/event-bus-type'; import { EVENT_BUS_TYPE } from '../common/event-bus-type';
import EmptyTip from '../empty-tip';
const propTypes = { const propTypes = {
path: PropTypes.string.isRequired, path: PropTypes.string.isRequired,
@@ -651,6 +652,7 @@ class DirentListView extends React.Component {
onDragLeave={this.onTableDragLeave} onDragLeave={this.onTableDragLeave}
onDrop={this.tableDrop} onDrop={this.tableDrop}
> >
{direntList.length > 0 &&
<table className={`table-hover ${isDesktop ? '' : 'table-thead-hidden'}`}> <table className={`table-hover ${isDesktop ? '' : 'table-thead-hidden'}`}>
{isDesktop ? ( {isDesktop ? (
<thead onMouseDown={this.onThreadMouseDown} onContextMenu={this.onThreadContextMenu}> <thead onMouseDown={this.onThreadMouseDown} onContextMenu={this.onThreadContextMenu}>
@@ -729,6 +731,10 @@ class DirentListView extends React.Component {
})} })}
</tbody> </tbody>
</table> </table>
}
{direntList.length === 0 &&
<EmptyTip text={gettext('No file')}/>
}
<Fragment> <Fragment>
<ContextMenu <ContextMenu
id={'dirent-container-menu'} id={'dirent-container-menu'}

View File

@@ -14,7 +14,7 @@ const propTypes = {
onAddFile: PropTypes.func.isRequired onAddFile: PropTypes.func.isRequired
}; };
class DirentNodeView extends React.Component { class DirentNoneView extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
@@ -88,6 +88,6 @@ class DirentNodeView extends React.Component {
} }
} }
DirentNodeView.propTypes = propTypes; DirentNoneView.propTypes = propTypes;
export default DirentNodeView; export default DirentNoneView;

View File

@@ -3,9 +3,9 @@ import PropTypes from 'prop-types';
import { mediaUrl } from '../utils/constants'; import { mediaUrl } from '../utils/constants';
import '../css/empty-tip.css'; import '../css/empty-tip.css';
function EmptyTip({ className, title, text, children }) { function EmptyTip({ className = '', title, text, children }) {
return ( return (
<div className='empty-tip'> <div className={`empty-tip ${className}`}>
<img src={`${mediaUrl}img/no-items-tip.png`} alt="" width="100" height="100" className="no-items-img-tip" /> <img src={`${mediaUrl}img/no-items-tip.png`} alt="" width="100" height="100" className="no-items-img-tip" />
{title && <span className="empty-tip-title">{title}</span>} {title && <span className="empty-tip-title">{title}</span>}
{text && <span className="empty-tip-text">{text}</span>} {text && <span className="empty-tip-text">{text}</span>}

View File

@@ -1,7 +1,9 @@
import React, { useCallback, useMemo } from 'react'; import React, { useCallback, useMemo } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import EmptyTip from '../../../../../components/empty-tip';
import { gettext } from '../../../utils';
const Main = ({ groups, overScan, columns, size, gap }) => { const GalleryMain = ({ groups, overScan, columns, size, gap }) => {
const imageHeight = useMemo(() => size + gap, [size, gap]); const imageHeight = useMemo(() => size + gap, [size, gap]);
const renderDisplayGroup = useCallback((group) => { const renderDisplayGroup = useCallback((group) => {
@@ -47,17 +49,20 @@ const Main = ({ groups, overScan, columns, size, gap }) => {
); );
}, [overScan, columns, size, imageHeight]); }, [overScan, columns, size, imageHeight]);
if (!Array.isArray(groups) || groups.length === 0) return null; if (!Array.isArray(groups) || groups.length === 0) {
return <EmptyTip text={gettext('No record')}/>;
}
return groups.map((group, index) => { return groups.map((group, index) => {
return renderDisplayGroup(group, index); return renderDisplayGroup(group, index);
}); });
}; };
Main.propTypes = { GalleryMain.propTypes = {
groups: PropTypes.array, groups: PropTypes.array,
overScan: PropTypes.object, overScan: PropTypes.object,
columns: PropTypes.number, columns: PropTypes.number,
size: PropTypes.number, size: PropTypes.number,
}; };
export default Main; export default GalleryMain;

View File

@@ -5,7 +5,7 @@ import { Utils } from '../../../../../utils/utils';
import { getDateDisplayString, PRIVATE_COLUMN_KEY } from '../../../_basic'; import { getDateDisplayString, PRIVATE_COLUMN_KEY } from '../../../_basic';
import { siteRoot, thumbnailSizeForGrid } from '../../../../../utils/constants'; import { siteRoot, thumbnailSizeForGrid } from '../../../../../utils/constants';
import { EVENT_BUS_TYPE, PER_LOAD_NUMBER } from '../../../constants'; import { EVENT_BUS_TYPE, PER_LOAD_NUMBER } from '../../../constants';
import Main from './main'; import GalleryMain from './gallery-main';
import toaster from '../../../../../components/toast'; import toaster from '../../../../../components/toast';
import './index.css'; import './index.css';
@@ -167,8 +167,12 @@ const Gallery = () => {
<div className="sf-metadata-gallery-container" ref={containerRef} onScroll={handleScroll} > <div className="sf-metadata-gallery-container" ref={containerRef} onScroll={handleScroll} >
{!isFirstLoading && ( {!isFirstLoading && (
<> <>
<Main groups={groups} size={imageSize} columns={columns} overScan={overScan} gap={IMAGE_GAP} /> <GalleryMain groups={groups} size={imageSize} columns={columns} overScan={overScan} gap={IMAGE_GAP} />
{isLoadingMore && (<div className="sf-metadata-gallery-loading-more"><CenteredLoading /></div>)} {isLoadingMore &&
<div className="sf-metadata-gallery-loading-more">
<CenteredLoading />
</div>
}
</> </>
)} )}
</div> </div>

View File

@@ -1,4 +1,4 @@
import React, { Component, Fragment } from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import RecordsHeader from './records-header'; import RecordsHeader from './records-header';
import Body from './body'; import Body from './body';
@@ -9,8 +9,9 @@ import { recalculate } from '../../../../../utils/column-utils';
import { SEQUENCE_COLUMN_WIDTH, CANVAS_RIGHT_INTERVAL, GROUP_ROW_TYPE, EVENT_BUS_TYPE } from '../../../../../constants'; import { SEQUENCE_COLUMN_WIDTH, CANVAS_RIGHT_INTERVAL, GROUP_ROW_TYPE, EVENT_BUS_TYPE } from '../../../../../constants';
import { import {
isWindowsBrowser, isWebkitBrowser, isMobile, getEventClassName, isWindowsBrowser, isWebkitBrowser, isMobile, getEventClassName,
addClassName, removeClassName, addClassName, removeClassName, gettext,
} from '../../../../../utils'; } from '../../../../../utils';
import EmptyTip from '../../../../../../../components/empty-tip';
import RecordMetrics from '../../../../../utils/record-metrics'; import RecordMetrics from '../../../../../utils/record-metrics';
import { isShiftKeyDown } from '../../../../../utils/keyboard-utils'; import { isShiftKeyDown } from '../../../../../utils/keyboard-utils';
import { getVisibleBoundaries } from '../../../../../utils/viewport'; import { getVisibleBoundaries } from '../../../../../utils/viewport';
@@ -665,8 +666,12 @@ class Records extends Component {
const hasSelectedRecord = this.hasSelectedRecord(); const hasSelectedRecord = this.hasSelectedRecord();
const isSelectedAll = RecordMetrics.isSelectedAll(recordIds, recordMetrics); const isSelectedAll = RecordMetrics.isSelectedAll(recordIds, recordMetrics);
if (recordsCount === 0) {
return (<EmptyTip text={gettext('No record')} />);
}
return ( return (
<Fragment> <>
<div <div
className={`sf-metadata-result-container ${this.isWindows ? 'windows-browser' : ''}`} className={`sf-metadata-result-container ${this.isWindows ? 'windows-browser' : ''}`}
ref={this.setResultContainerRef} ref={this.setResultContainerRef}
@@ -721,7 +726,7 @@ class Records extends Component {
getRecordsSummaries={() => {}} getRecordsSummaries={() => {}}
loadAll={this.props.loadAll} loadAll={this.props.loadAll}
/> />
</Fragment> </>
); );
} }
} }

View File

@@ -118,7 +118,7 @@ class RecordsFooter extends React.Component {
return gettext('xxx cells selected').replace('xxx', selectedCellsCount); return gettext('xxx cells selected').replace('xxx', selectedCellsCount);
} }
let recordsCountText = gettext('No record'); let recordsCountText;
if (recordsCount > 1) { if (recordsCount > 1) {
recordsCountText = gettext('xxx records').replace('xxx', recordsCount); recordsCountText = gettext('xxx records').replace('xxx', recordsCount);
} else if (recordsCount === 1) { } else if (recordsCount === 1) {