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

[dir view] list view: added support for mobile (#4037)

This commit is contained in:
llj
2019-08-30 18:10:48 +08:00
committed by Daniel Pan
parent 700cff2aba
commit 64583c8eb9
2 changed files with 138 additions and 62 deletions

View File

@@ -2,6 +2,7 @@ import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import MD5 from 'MD5';
import { UncontrolledTooltip } from 'reactstrap';
import { Dropdown, DropdownToggle, DropdownItem } from 'reactstrap';
import { gettext, siteRoot, mediaUrl, username } from '../../utils/constants';
import { Utils } from '../../utils/utils';
import { seafileAPI } from '../../utils/seafile-api';
@@ -70,6 +71,7 @@ class DirentListItem extends React.Component {
isDropTipshow: false,
isEditFileTagShow: false,
isPermissionDialogOpen: false,
isOpMenuOpen: false // for mobile
};
}
@@ -86,6 +88,12 @@ class DirentListItem extends React.Component {
}
}
toggleOpMenu = () => {
this.setState({
isOpMenuOpen: !this.state.isOpMenuOpen
});
}
//UI Interactive
onMouseEnter = () => {
if (!this.props.isItemFreezed) {
@@ -186,6 +194,11 @@ class DirentListItem extends React.Component {
this.setState({isShareDialogShow: !this.state.isShareDialogShow});
}
onMobileMenuItemClick = (e) => {
const operation = e.target.getAttribute('data-op');
this.onMenuItemClick(operation, e);
}
onMenuItemClick = (operation, event) => {
switch(operation) {
case 'Download':
@@ -586,70 +599,121 @@ class DirentListItem extends React.Component {
trClass += (activeDirent && activeDirent.name === dirent.name) ? 'tr-active' : '';
trClass += dirent.isSelected? 'tr-active' : '';
let lockedInfo = gettext('locked by {name}');
lockedInfo = lockedInfo.replace('{name}', dirent.lock_owner_name);
let lockedInfo = gettext('locked by {name}').replace('{name}', dirent.lock_owner_name);
const isDesktop = Utils.isDesktop();
const desktopItem = (
<tr
className={trClass}
draggable="true"
onMouseEnter={this.onMouseEnter}
onMouseOver={this.onMouseOver}
onMouseLeave={this.onMouseLeave}
onClick={this.onDirentClick}
onDragStart={this.onItemDragStart}
onDragEnter={this.onItemDragEnter}
onDragOver={this.onItemDragOver}
onDragLeave={this.onItemDragLeave}
onDrop={this.onItemDragDrop}
onMouseDown={this.onItemMouseDown}
onContextMenu={this.onItemContextMenu}
>
<td className={`pl10 ${this.state.isDragTipShow ? 'tr-drag-effect' : ''}`}>
<input type="checkbox" className="vam" onChange={this.onItemSelected} checked={dirent.isSelected}/>
</td>
<td className="pl10">
{dirent.starred !== undefined && !dirent.starred && <i className="far fa-star star-empty cursor-pointer" onClick={this.onItemStarred}></i>}
{dirent.starred !== undefined && dirent.starred && <i className="fas fa-star cursor-pointer" onClick={this.onItemStarred}></i>}
</td>
<td className="pl10">
<div className="dir-icon">
{dirent.encoded_thumbnail_src ?
<img ref='drag_icon' src={`${siteRoot}${dirent.encoded_thumbnail_src}`} className="thumbnail cursor-pointer" onClick={this.onItemClick} alt="" /> :
<img ref='drag_icon' src={iconUrl} width="24" alt='' />
}
{dirent.is_locked && <img className="locked" src={mediaUrl + 'img/file-locked-32.png'} alt={gettext('locked')} title={lockedInfo}/>}
<div ref="empty_content" style={{position: 'absolute', width: '1px', height: '1px'}}></div>
</div>
</td>
<td className="name">
{this.state.isRenameing ?
<Rename hasSuffix={dirent.type !== 'dir'} name={dirent.name} onRenameConfirm={this.onRenameConfirm} onRenameCancel={this.onRenameCancel} /> :
<a href={dirent.type === 'dir' ? dirHref : fileHref} onClick={this.onItemClick}>{dirent.name}</a>
}
</td>
<td className="tag-list-title">
{(dirent.type !== 'dir' && dirent.file_tags && dirent.file_tags.length > 0) && (
<Fragment>
<div id={`tag-list-title-${toolTipID}`} className="dirent-item tag-list tag-list-stacked">
{dirent.file_tags.map((fileTag, index) => {
let length = dirent.file_tags.length;
return (
<span className="file-tag" key={fileTag.id} style={{zIndex:length - index, backgroundColor:fileTag.color}}></span>
);
})}
</div>
<UncontrolledTooltip target={`tag-list-title-${toolTipID}`} placement="bottom">
{tagTitle}
</UncontrolledTooltip>
</Fragment>
)}
</td>
<td className="operation">{this.renderItemOperation()}</td>
<td className="file-size">{dirent.size && dirent.size}</td>
<td className="last-update">{dirent.mtime_relative}</td>
</tr>
);
const mobileItem = (
<tr>
<td>
<div className="dir-icon">
{dirent.encoded_thumbnail_src ?
<img src={`${siteRoot}${dirent.encoded_thumbnail_src}`} className="thumbnail cursor-pointer" onClick={this.onItemClick} alt="" /> :
<img src={iconUrl} width="24" alt="" />
}
{dirent.is_locked && <img className="locked" src={mediaUrl + 'img/file-locked-32.png'} alt={gettext('locked')} title={lockedInfo}/>}
</div>
</td>
<td>
{this.state.isRenameing ?
<Rename hasSuffix={dirent.type !== 'dir'} name={dirent.name} onRenameConfirm={this.onRenameConfirm} onRenameCancel={this.onRenameCancel} /> :
<a href={dirent.type === 'dir' ? dirHref : fileHref} onClick={this.onItemClick}>{dirent.name}</a>
}
<br />
{dirent.size && <span className="item-meta-info">{dirent.size}</span>}
<span className="item-meta-info">{dirent.mtime_relative}</span>
</td>
<td>
<Dropdown isOpen={this.state.isOpMenuOpen} toggle={this.toggleOpMenu}>
<DropdownToggle
tag="i"
className="sf-dropdown-toggle fa fa-ellipsis-v ml-0"
title={gettext('More Operations')}
data-toggle="dropdown"
aria-expanded={this.state.isOpMenuOpen}
/>
<div className={this.state.isOpMenuOpen ? '' : 'd-none'} onClick={this.toggleOpMenu}>
<div className="mobile-operation-menu-bg-layer"></div>
<div className="mobile-operation-menu">
{dirent.starred !== undefined &&
<DropdownItem className="mobile-menu-item" onClick={this.onItemStarred}>{dirent.starred ? gettext('Unstar') : gettext('Star')}</DropdownItem>}
{this.props.getDirentItemMenuList(dirent, true).map((item, index) => {
if (item != 'Divider' && item.key != 'Open via Client') {
return (
<DropdownItem className="mobile-menu-item" key={index} data-op={item.key} onClick={this.onMobileMenuItemClick}>{item.value}</DropdownItem>
);
}
})}
</div>
</div>
</Dropdown>
</td>
</tr>
);
return (
<Fragment>
<tr
className={trClass}
draggable="true"
onMouseEnter={this.onMouseEnter}
onMouseOver={this.onMouseOver}
onMouseLeave={this.onMouseLeave}
onClick={this.onDirentClick}
onDragStart={this.onItemDragStart}
onDragEnter={this.onItemDragEnter}
onDragOver={this.onItemDragOver}
onDragLeave={this.onItemDragLeave}
onDrop={this.onItemDragDrop}
onMouseDown={this.onItemMouseDown}
onContextMenu={this.onItemContextMenu}
>
<td className={`pl10 ${this.state.isDragTipShow ? 'tr-drag-effect' : ''}`}>
<input type="checkbox" className="vam" onChange={this.onItemSelected} checked={dirent.isSelected}/>
</td>
<td className="pl10">
{dirent.starred !== undefined && !dirent.starred && <i className="far fa-star star-empty cursor-pointer" onClick={this.onItemStarred}></i>}
{dirent.starred !== undefined && dirent.starred && <i className="fas fa-star cursor-pointer" onClick={this.onItemStarred}></i>}
</td>
<td className="pl10">
<div className="dir-icon">
{dirent.encoded_thumbnail_src ?
<img ref='drag_icon' src={`${siteRoot}${dirent.encoded_thumbnail_src}`} className="thumbnail cursor-pointer" onClick={this.onItemClick} alt="" /> :
<img ref='drag_icon' src={iconUrl} width="24" alt='' />
}
{dirent.is_locked && <img className="locked" src={mediaUrl + 'img/file-locked-32.png'} alt={gettext('locked')} title={lockedInfo}/>}
<div ref="empty_content" style={{position: 'absolute', width: '1px', height: '1px'}}></div>
</div>
</td>
<td className="name">
{this.state.isRenameing ?
<Rename hasSuffix={dirent.type !== 'dir'} name={dirent.name} onRenameConfirm={this.onRenameConfirm} onRenameCancel={this.onRenameCancel} /> :
<a href={dirent.type === 'dir' ? dirHref : fileHref} onClick={this.onItemClick}>{dirent.name}</a>
}
</td>
<td className="tag-list-title">
{(dirent.type !== 'dir' && dirent.file_tags && dirent.file_tags.length > 0) && (
<Fragment>
<div id={`tag-list-title-${toolTipID}`} className="dirent-item tag-list tag-list-stacked">
{dirent.file_tags.map((fileTag, index) => {
let length = dirent.file_tags.length;
return (
<span className="file-tag" key={fileTag.id} style={{zIndex:length - index, backgroundColor:fileTag.color}}></span>
);
})}
</div>
<UncontrolledTooltip target={`tag-list-title-${toolTipID}`} placement="bottom">
{tagTitle}
</UncontrolledTooltip>
</Fragment>
)}
</td>
<td className="operation">{this.renderItemOperation()}</td>
<td className="file-size">{dirent.size && dirent.size}</td>
<td className="last-update">{dirent.mtime_relative}</td>
</tr>
{isDesktop ? desktopItem : mobileItem}
{this.state.isMoveDialogShow &&
<ModalPortal>
<MoveDirentDialog

View File

@@ -652,6 +652,8 @@ class DirentListView extends React.Component {
const sortBySize = sortBy == 'size';
const sortIcon = sortOrder == 'asc' ? <span className="fas fa-caret-up"></span> : <span className="fas fa-caret-down"></span>;
const isDesktop = Utils.isDesktop();
return (
<div
className={`table-container ${this.state.isListDropTipShow ? 'table-drop-active' : ''}`}
@@ -663,7 +665,8 @@ class DirentListView extends React.Component {
onDragLeave={this.onTableDragLeave}
onDrop={this.tableDrop}
>
<table>
<table className={`table-hover ${isDesktop ? '': 'table-thead-hidden'}`}>
{isDesktop ? (
<thead onMouseDown={this.onThreadMouseDown} onContextMenu={this.onThreadContextMenu}>
<tr>
<th width="3%" className="pl10">
@@ -678,6 +681,15 @@ class DirentListView extends React.Component {
<th width="15%"><a className="d-block table-sort-op" href="#" onClick={this.sortByTime}>{gettext('Last Update')} {sortByTime && sortIcon}</a></th>
</tr>
</thead>
) : (
<thead>
<tr>
<th width="12%"></th>
<th width="80%"></th>
<th width="8%"></th>
</tr>
</thead>
)}
<tbody>
{direntList.map((dirent, index) => {
return (