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

Table module optimized (#2727)

This commit is contained in:
杨顺强
2018-12-28 11:12:24 +08:00
committed by Daniel Pan
parent f20f418f29
commit 8637abde8d
35 changed files with 294 additions and 362 deletions

View File

@@ -52,7 +52,7 @@ class Notification extends React.Component {
<div className="outer-caret up-outer-caret"><div className="inner-caret"></div></div>
<div className="sf-popover-hd ovhd">
<h3 className="sf-popover-title title">{gettext('Notifications')}</h3>
<a href="#" onClick={this.onClick} title={gettext('Close')} aria-label={gettext('Close')} className="sf-popover-close js-close sf2-icon-x1 op-icon float-right"></a>
<a href="#" onClick={this.onClick} title={gettext('Close')} aria-label={gettext('Close')} className="sf-popover-close js-close sf2-icon-x1 action-icon float-right"></a>
</div>
<div className="sf-popover-con">
<ul className="notice-list" dangerouslySetInnerHTML={{__html: notice_html}}></ul>

View File

@@ -30,8 +30,8 @@ class ShareRepoListItem extends React.Component {
let repo = this.props.repo;
return (
<tr>
<td className="select"><input type="checkbox" className="vam" name="repo" onChange={this.onRepoSelect} /></td>
<td className="icon"><img src={siteRoot + 'media/img/lib/48/lib.png'} width="24" alt={gettext('icon')} /></td>
<td className="text-center"><input type="checkbox" className="vam" name="repo" onChange={this.onRepoSelect} /></td>
<td className="text-center"><img src={siteRoot + 'media/img/lib/48/lib.png'} alt={gettext('icon')} /></td>
<td className="name">{gettext(repo.repo_name)}</td>
<td>{moment(repo.last_modified).fromNow()}</td>
<td>

View File

@@ -50,7 +50,7 @@ class GroupItem extends React.Component {
</td>
<td>
<span
className={`sf2-icon-x3 op-icon ${this.state.isOperationShow ? '' : 'hide'}`}
className={`sf2-icon-x3 action-icon ${this.state.isOperationShow ? '' : 'hide'}`}
onClick={this.deleteShareItem}
title={gettext('Delete')}
>

View File

@@ -49,7 +49,7 @@ class UserItem extends React.Component {
</td>
<td>
<span
className={`sf2-icon-x3 op-icon ${this.state.isOperationShow ? '' : 'hide'}`}
className={`sf2-icon-x3 action-icon ${this.state.isOperationShow ? '' : 'hide'}`}
onClick={this.deleteShareItem}
title={gettext('Delete')}
>

View File

@@ -65,8 +65,8 @@ class WikiSelectDialog extends React.Component {
{this.state.repos.map((repo, index) => {
return (
<tr key={index}>
<td className="select"><input type="radio" className="vam" name="repo" value={repo.repo_id} onChange={this.onChange.bind(this, repo)} /></td>
<td><img src={siteRoot + 'media/img/lib/48/lib.png'} width="24" alt={gettext('icon')} /></td>
<td className="text-center"><input type="radio" className="vam" name="repo" value={repo.repo_id} onChange={this.onChange.bind(this, repo)} /></td>
<td className="text-center"><img src={siteRoot + 'media/img/lib/48/lib.png'} alt={gettext('icon')} /></td>
<td>{gettext(repo.repo_name)}</td>
<td>{moment(repo.last_modified).fromNow()}</td>
</tr>

View File

@@ -15,6 +15,8 @@ import MoveDirentDialog from '../dialog/move-dirent-dialog';
import CopyDirentDialog from '../dialog/copy-dirent-dialog';
import ShareDialog from '../dialog/share-dialog';
import '../../css/dirent-list-item.css';
const propTypes = {
path: PropTypes.string.isRequired,
repoID: PropTypes.string.isRequired,
@@ -404,14 +406,14 @@ class DirentListItem extends React.Component {
return (
<Fragment>
<tr className={this.state.highlight ? 'tr-highlight' : ''} onMouseEnter={this.onMouseEnter} onMouseOver={this.onMouseOver} onMouseLeave={this.onMouseLeave}>
<td className="select">
<td className="text-center">
<input type="checkbox" className="vam" onChange={this.onItemSelected} checked={dirent.isSelected}/>
</td>
<td className="star" onClick={this.onItemStarred}>
{dirent.starred !== undefined && !dirent.starred && <i className="far fa-star empty"></i>}
<td className="text-center cursor-pointer" onClick={this.onItemStarred}>
{dirent.starred !== undefined && !dirent.starred && <i className="far fa-star star-empty"></i>}
{dirent.starred !== undefined && dirent.starred && <i className="fas fa-star"></i>}
</td>
<td className="icon">
<td className="text-center">
<div className="dir-icon">
<img src={dirent.type === 'dir' ? siteRoot + 'media/img/folder-192.png' : siteRoot + 'media/img/file/192/txt.png'} alt=''></img>
{dirent.is_locked && <img className="locked" src={siteRoot + 'media/img/file-locked-32.png'} alt={gettext('locked')}></img>}
@@ -446,13 +448,13 @@ class DirentListItem extends React.Component {
<div className="operations">
<ul className="operation-group">
<li className="operation-group-item">
<i className="sf2-icon-download" title={gettext('Download')} onClick={this.onItemDownload}></i>
<i className="op-icon sf2-icon-download" title={gettext('Download')} onClick={this.onItemDownload}></i>
</li>
<li className="operation-group-item">
<i className="sf2-icon-share" title={gettext('Share')} onClick={this.onItemShare}></i>
<i className="op-icon sf2-icon-share" title={gettext('Share')} onClick={this.onItemShare}></i>
</li>
<li className="operation-group-item">
<i className="sf2-icon-delete" title={gettext('Delete')} onClick={this.onItemDelete}></i>
<i className="op-icon sf2-icon-delete" title={gettext('Delete')} onClick={this.onItemDelete}></i>
</li>
<li className="operation-group-item">
<i className="sf2-icon-caret-down sf-dropdown-toggle" title={gettext('More Operations')} onClick={this.onItemMenuToggle}></i>

View File

@@ -106,7 +106,7 @@ class DirentListView extends React.Component {
<table>
<thead>
<tr>
<th width="3%" className="select">
<th width="3%" className="text-center">
<input type="checkbox" className="vam" onChange={this.props.onAllItemSelected} checked={this.props.isAllItemSelected}/>
</th>
<th width="3%">{/*icon */}</th>

View File

@@ -58,7 +58,7 @@ class DraftListItem extends React.Component {
localTime = moment(localTime).fromNow();
return (
<tr className={this.state.highlight} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>
<td className="icon"><img src={siteRoot + 'media/img/file/192/txt.png'} alt='icon' /></td>
<td className="text-center"><img src={siteRoot + 'media/img/file/192/txt.png'} alt='icon' /></td>
<td className="name" >
<a href={draftUrl} target="_blank">{fileName}</a>
</td>
@@ -72,7 +72,7 @@ class DraftListItem extends React.Component {
}
</td>
<td className="update">{localTime}</td>
<td className="menu-toggle">
<td className="text-center cursor-pointer">
{
this.props.draft.review_status !== 'open' &&
<MenuControl

View File

@@ -19,7 +19,7 @@ class Logo extends React.Component {
<img src={mediaUrl + logoPath} height={logoHeight} width={logoWidth} title={siteTitle} alt="logo" />
</a>
<a
className="sf2-icon-x1 sf-popover-close side-panel-close op-icon d-md-none"
className="sf2-icon-x1 sf-popover-close side-panel-close action-icon d-md-none"
onClick={this.closeSide}
title="Close"
aria-label="Close"

View File

@@ -81,7 +81,7 @@ class PermissionEditor extends React.Component {
<span
title={gettext('Edit')}
style={{fontSize: '0.875rem', marginLeft: '0.5rem'}}
className="fa fa-pencil op-icon"
className="fa fa-pencil action-icon"
onClick={this.onEidtPermission}>
</span>
)}

View File

@@ -103,11 +103,11 @@ class ReviewListItem extends React.Component {
return (
<tr className={this.state.highlight} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>
<td className="icon" style={{width: '4%'}}><img src={siteRoot + 'media/img/file/192/txt.png'} alt="icon"/></td>
<td className="name" style={{width: '26%'}}><a href={reviewUrl} target="_blank">{fileName}</a></td>
<td className="text-center" style={{width: '4%'}}><img src={siteRoot + 'media/img/file/192/txt.png'} alt="icon"/></td>
<td style={{width: '26%'}}><a href={reviewUrl} target="_blank">{fileName}</a></td>
<td className='library' style={{width: '25%'}}>{item.draft_origin_repo_name}</td>
<td className="update" style={{width: '20%'}}>{localTime}</td>
<td className="author" style={{width: '10%'}}><img className="avatar avatar-sm avatar-with-tooltip" id={'tip-' + item.id} src={item.author.avatar_url} alt={item.user_name} /></td>
<td className="author" style={{width: '10%'}}><img className="avatar avatar-sm cursor-pointer" id={'tip-' + item.id} src={item.author.avatar_url} alt={item.user_name} /></td>
<td className="reviewer" style={{width: '15%'}}><Reviewers item={item}/></td>
<Tooltip placement="bottom-end" isOpen={this.state.authorTipOpen} target={'tip-' + item.id} toggle={this.toggle}>
{item.author.user_name}

View File

@@ -206,8 +206,8 @@ class SharedRepoListItem extends React.Component {
return (
<Dropdown isOpen={this.state.isItemMenuShow} toggle={this.toggleOperationMenu}>
<DropdownToggle
tag="a"
className="sf2-icon-caret-down item-operation-menu-toggle-icon op-icon"
tag="i"
className="sf-dropdown-toggle sf2-icon-caret-down"
title={gettext('More Operations')}
data-toggle="dropdown"
aria-expanded={this.state.isItemMenuShow}
@@ -239,9 +239,9 @@ class SharedRepoListItem extends React.Component {
// scene two: (share, unshare), (share), (unshare)
operations = this.generatorOperations();
}
const shareOperation = <a href="#" className="sf2-icon-share sf2-x op-icon" title={gettext("Share")} onClick={this.onItemShare}></a>;
const unshareOperation = <a href="#" className="sf2-icon-x3 sf2-x op-icon" title={gettext("Unshare")} onClick={this.onItemUnshare}></a>
const deleteOperation = <a href="#" className="sf2-icon-delete sf2-x op-icon" title={gettext('Delete')} onClick={this.onItemDelete}></a>;
const shareOperation = <a href="#" className="op-icon sf2-icon-share" title={gettext("Share")} onClick={this.onItemShare}></a>;
const unshareOperation = <a href="#" className="op-icon sf2-icon-x3" title={gettext("Unshare")} onClick={this.onItemUnshare}></a>
const deleteOperation = <a href="#" className="op-icon sf2-icon-delete" title={gettext('Delete')} onClick={this.onItemDelete}></a>;
if (this.isDeparementOnwerGroupMember) {
return (
@@ -250,8 +250,8 @@ class SharedRepoListItem extends React.Component {
{deleteOperation}
<Dropdown isOpen={this.state.isItemMenuShow} toggle={this.toggleOperationMenu}>
<DropdownToggle
tag="a"
className="sf2-icon-caret-down item-operation-menu-toggle-icon op-icon"
tag="i"
className="sf-dropdown-toggle sf2-icon-caret-down"
title={gettext('More Operations')}
data-toggle="dropdown"
aria-expanded={this.state.isItemMenuShow}

View File

@@ -24,7 +24,7 @@ class GroupsToolbar extends React.Component {
<div className="cur-view-toolbar border-left-show">
<div className="operation">
<Button color="btn btn-secondary operation-item" onClick={this.props.toggleAddGroupModal}>
<i className="fas fa-plus-square op-icon"></i>{gettext("New Group")}
<i className="fas fa-plus-square action-icon"></i>{gettext("New Group")}
</Button>
</div>
<span title="Side Nav Menu" onClick={onShowSidePanel}

View File

@@ -96,10 +96,10 @@ class MutipleDirOperationToolbar extends React.Component {
return (
<Fragment>
<div className="operation multiple-dirents-operation">
<button className="btn btn-secondary operation-item op-icon sf2-icon-move" title={gettext('Move')} onClick={this.onMoveToggle}></button>
<button className="btn btn-secondary operation-item op-icon sf2-icon-copy" title={gettext('Copy')} onClick={this.onCopyToggle}></button>
<button className="btn btn-secondary operation-item op-icon sf2-icon-delete" title={gettext('Delete')} onClick={this.props.onItemsDelete}></button>
<button className="btn btn-secondary operation-item op-icon sf2-icon-download" title={gettext('Download')} onClick={this.onItemsDownload}></button>
<button className="btn btn-secondary operation-item action-icon sf2-icon-move" title={gettext('Move')} onClick={this.onMoveToggle}></button>
<button className="btn btn-secondary operation-item action-icon sf2-icon-copy" title={gettext('Copy')} onClick={this.onCopyToggle}></button>
<button className="btn btn-secondary operation-item action-icon sf2-icon-delete" title={gettext('Delete')} onClick={this.props.onItemsDelete}></button>
<button className="btn btn-secondary operation-item action-icon sf2-icon-download" title={gettext('Download')} onClick={this.onItemsDownload}></button>
</div>
{this.state.isMoveDialogShow &&
<MoveDirentDialog

View File

@@ -42,7 +42,7 @@ class RepoViewToolbar extends React.Component {
<span className="sf2-icon-menu side-nav-toggle hidden-md-up d-md-none" title="Side Nav Menu" onClick={this.props.onShowSidePanel}></span>
<div className="operation">
<button className="btn btn-secondary operation-item" title={gettext('New Library')} onClick={this.onCreateToggle}>
<i className="fas fa-plus-square op-icon"></i>
<i className="fas fa-plus-square action-icon"></i>
{gettext('New Library')}
</button>
{this.props.libraryType !== 'group' && (

View File

@@ -36,7 +36,7 @@ class TreeDirList extends React.Component {
let href = siteRoot + 'wikis' + node.path;
return (
<tr className={this.state.highlight ? 'tr-highlight' : ''} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>
<td className="icon">
<td className="text-center">
<img src={node.type === 'dir' ? siteRoot + 'media/img/folder-192.png' : siteRoot + 'media/img/file/192/txt.png'} alt='icon'></img>
</td>
<td className="name">

View File

@@ -150,7 +150,7 @@ class WikiListItem extends Component {
</td>
<td><a href={userProfileURL} target='_blank'>{gettext(wiki.owner_nickname)}</a></td>
<td>{moment(wiki.updated_at).fromNow()}</td>
<td className="menu-toggle">
<td className="text-center cursor-pointer">
{this.state.isShowMenuControl && (
<Dropdown isOpen={this.state.isShowWikiMenu} toggle={this.onMenuToggle}>
<DropdownToggle

View File

@@ -0,0 +1,25 @@
.operations {
display: flex;
}
.operations .operation-group {
list-style: none;
}
.operation-group .operation-group-item {
display: inline-block;
}
.star-empty {
color: #d0d0d0;
}
.dir-icon {
position: relative;
}
.dir-icon .locked {
position: absolute;
width: 1rem;
height: 1rem;
top: 50%;
left: 50%;
}

View File

@@ -8,7 +8,7 @@
padding: 0.5rem 1rem;
}
.history-header .title {
font-size: 1.5rem;
font-size: 1.25rem;
line-height: 1rem;
}

View File

@@ -3,20 +3,17 @@ import PropTypes from 'prop-types';
import { seafileAPI } from '../../utils/seafile-api';
import { gettext, siteRoot } from '../../utils/constants';
import { Utils } from '../../utils/utils';
import Loading from '../../components/loading';
const contentPropTypes = {
data: PropTypes.object.isRequired,
isLoadingMore: PropTypes.bool.isRequired,
items: PropTypes.array.isRequired,
};
class FileActivitiesContent extends Component {
render() {
let {loading, error_msg, items, has_more} = this.props.data;
if (loading) {
return <span className="loading-icon loading-tip"></span>;
} else if (error_msg) {
return <p className="error text-center">{error_msg}</p>;
} else {
let {items, isLoadingMore} = this.props;
return (
<Fragment>
<table className="table table-hover table-vcenter">
@@ -31,12 +28,10 @@ class FileActivitiesContent extends Component {
</thead>
<TableBody items={items} />
</table>
{has_more ? <span className="loading-icon loading-tip"></span> : ''}
{error_msg ? <p className="error text-center">{error_msg}</p> : ''}
{isLoadingMore ? <span className="loading-icon loading-tip"></span> : ''}
</Fragment>
);
}
}
}
FileActivitiesContent.propTypes = contentPropTypes;
@@ -169,64 +164,63 @@ class FilesActivities extends Component {
constructor(props) {
super(props);
this.state = {
loading: true,
error_msg: '',
events: {},
errorMsg: '',
isFirstLoading: true,
isLoadingMore: false,
currentPage: 1,
hasMore: true,
items: [],
page: 1,
has_more: false
};
this.handleScroll = this.handleScroll.bind(this);
}
componentDidMount() {
const pageNum = 1;
const avatarSize = 72;
seafileAPI.listActivities(pageNum, avatarSize).then(res => {
// not logged in
if (res.status == 403) {
this.setState({
loading: false,
error_msg: gettext('Permission denied')
});
} else {
let currentPage = this.state.currentPage;
seafileAPI.listActivities(currentPage, avatarSize).then(res => {
// {"events":[...]}
this.setState({
loading: false,
items: res.data.events,
has_more: res.data.events.length < 25 ? false : true
currentPage: currentPage + 1,
isFirstLoading: false,
hasMore: true,
});
}).catch(error => {
if (error.response.status == 403) {
this.setState({
isFirstLoading: false,
errorMsg: gettext('Permission denied')
});
}
});
}
getMore() {
const pageNum = this.state.page + 1;
this.setState({page: pageNum});
seafileAPI.listActivities(pageNum).then(res => {
if (res.status == 403) {
this.setState({
loading: false,
error_msg: gettext('Permission denied')
});
} else {
this.setState({isLoadingMore: true});
let currentPage = this.state.currentPage;
seafileAPI.listActivities(currentPage).then(res => {
// {"events":[...]}
this.setState({
loading: false,
isLoadingMore: false,
items: [...this.state.items, ...res.data.events],
has_more: res.data.events.length < 25 ? false : true
currentPage: currentPage + 1,
hasMore: res.data.events.length === 0 ? false : true
});
}).catch(error => {
if (error.response.status == 403) {
this.setState({
isLoadingMore: false,
errorMsg: gettext('Permission denied')
});
}
});
}
handleScroll(event) {
handleScroll = (event) => {
const clientHeight = event.target.clientHeight;
const scrollHeight = event.target.scrollHeight;
const scrollTop = event.target.scrollTop;
const isBottom = (clientHeight + scrollTop + 1 >= scrollHeight);
if (this.state.has_more && isBottom) { // scroll to the bottom
if (this.state.hasMore && isBottom) { // scroll to the bottom
this.getMore();
}
}
@@ -239,7 +233,13 @@ class FilesActivities extends Component {
<h3 className="sf-heading">{gettext('Activities')}</h3>
</div>
<div className="cur-view-content" onScroll={this.handleScroll}>
<FileActivitiesContent data={this.state} />
{this.state.isFirstLoading && <Loading />}
{(!this.state.isFirstLoading && this.state.errorMsg) &&
<p className="error text-center">{this.state.errorMsg}</p>
}
{!this.state.isFirstLoading &&
<FileActivitiesContent items={this.state.items} isLoadingMore={this.state.isLoadingMore}/>
}
</div>
</div>
</div>

View File

@@ -304,7 +304,7 @@ class GroupView extends React.Component {
<span className="sf2-icon-menu side-nav-toggle hidden-md-up d-md-none" title="Side Nav Menu" onClick={this.props.onShowSidePanel}></span>
<div className="operation">
<button className="btn btn-secondary operation-item" title={gettext('New Library')} onClick={this.onCreateRepoToggle}>
<i className="fas fa-plus-square op-icon"></i>
<i className="fas fa-plus-square action-icon"></i>
{gettext('New Library')}
</button>
</div>
@@ -327,13 +327,13 @@ class GroupView extends React.Component {
<div className="path-tool">
{ (isShowSettingIcon && this.state.isStaff) &&
<React.Fragment>
<a href="#" className="sf2-icon-cog1 op-icon group-top-op-icon" title="Settings" id="settings"
<a href="#" className="sf2-icon-cog1 action-icon group-top-action-icon" title="Settings" id="settings"
onClick={this.toggleGroupDropdown}></a>
<Popover placement="bottom" isOpen={this.state.showGroupDropdown} target="settings"
toggle={this.toggleGroupDropdown} hideArrow={true} className="sf-popover">
<div className="sf-popover-hd sf-popover-title">
<span>{gettext('Settings')}</span>
<a href="#" className="sf-popover-close js-close sf2-icon-x1 op-icon"
<a href="#" className="sf-popover-close js-close sf2-icon-x1 action-icon"
onClick={this.toggleGroupDropdown}></a>
</div>
<div className="sf-popover-con">
@@ -359,7 +359,7 @@ class GroupView extends React.Component {
</React.Fragment>
}
<a href="#"
className="sf2-icon-user2 op-icon group-top-op-icon"
className="sf2-icon-user2 action-icon group-top-action-icon"
title={gettext('Members')} id="groupMembers"
onClick={() => this.toggleGroupMembersPopover('open')}>
</a>
@@ -367,7 +367,7 @@ class GroupView extends React.Component {
toggle={this.toggleGroupMembersPopover} hideArrow={true} className="sf-popover">
<div className="sf-popover-hd sf-popover-title">
<span>{gettext('Members')}</span>
<a href="#" className="sf-popover-close js-close sf2-icon-x1 op-icon"
<a href="#" className="sf-popover-close js-close sf2-icon-x1 action-icon"
onClick={this.toggleGroupMembersPopover}></a>
</div>
<div className="sf-popover-con">

View File

@@ -118,7 +118,7 @@ class Item extends Component {
const data = this.props.data;
let opClasses = 'sf2-icon-delete unlink-device op-icon';
let opClasses = 'sf2-icon-delete unlink-device action-icon';
opClasses += this.state.showOpIcon ? '' : ' invisible';
const desktopItem = (

View File

@@ -178,9 +178,9 @@ class Item extends Component {
data.url = `${siteRoot}library/${data.repo_id}/${Utils.encodePath(data.repo_name)}/`;
let iconVisibility = this.state.showOpIcon ? '' : ' invisible';
let shareIconClassName = 'sf2-icon-share sf2-x op-icon' + iconVisibility;
let deleteIconClassName = 'sf2-icon-delete sf2-x op-icon' + iconVisibility;
let operationMenuToggleIconClassName = 'sf2-icon-caret-down item-operation-menu-toggle-icon op-icon';
let shareIconClassName = 'op-icon sf2-icon-share' + iconVisibility;
let deleteIconClassName = 'op-icon sf2-icon-delete' + iconVisibility;
let operationMenuToggleIconClassName = 'sf-dropdown-toggle sf2-icon-caret-down';
if (window.innerWidth >= 768) {
operationMenuToggleIconClassName += iconVisibility;
}
@@ -189,8 +189,7 @@ class Item extends Component {
const commonToggle = (
<DropdownToggle
tag="a"
href="#"
tag="i"
className={operationMenuToggleIconClassName}
title={gettext('More Operations')}
// onClick={this.clickOperationMenuToggle}
@@ -258,7 +257,7 @@ class Item extends Component {
}
</td>
<td>{data.repo_name ? desktopOperations : ''}</td>
<td>{Utils.formatSize({bytes: data.size})}</td>
<td>{Utils.bytesToSize(data.size)}</td>
{storages.length ? <td>{data.storage_name}</td> : null}
<td title={moment(data.last_modified).format('llll')}>{moment(data.last_modified).fromNow()}</td>
</tr>
@@ -285,7 +284,7 @@ class Item extends Component {
<Link to={data.url}>{data.repo_name}</Link> :
gettext('Broken (please contact your administrator to fix this library)')}
<br />
<span className="item-meta-info">{Utils.formatSize({bytes: data.size})}</span>
<span className="item-meta-info">{Utils.bytesToSize(data.size)}</span>
<span className="item-meta-info" title={moment(data.last_modified).format('llll')}>{moment(data.last_modified).fromNow()}</span>
</td>
<td>{data.repo_name ? mobileOperations : ''}</td>

View File

@@ -150,12 +150,12 @@ class DeletedRepoItem extends Component {
return (
<tr className={this.state.highlight ? 'tr-highlight' : ''} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>
<td className="icon"><img src={siteRoot + 'media/img/lib/48/lib.png'} alt='icon' /></td>
<td className="text-center"><img src={siteRoot + 'media/img/lib/48/lib.png'} alt='' /></td>
<td className="name">{this.props.repo.repo_name}</td>
<td className="update">{localTime}</td>
<td>
{this.state.highlight && (
<a href="#" onClick={this.restoreDeletedRepo} className="sf2-icon-reply sf2-x repo-share-btn op-icon" title={gettext('Restore')} aria-label={gettext('Restore')}></a>
<a href="#" onClick={this.restoreDeletedRepo} className="op-icon sf2-icon-reply repo-share-btn" title={gettext('Restore')} aria-label={gettext('Restore')}></a>
)}
</td>
</tr>

View File

@@ -179,7 +179,7 @@ class SidePanel extends Component {
<a href={siteRoot} id="logo">
<img src={mediaUrl + logoPath} title={siteTitle} alt="logo" width={logoWidth} height={logoHeight} />
</a>
<a title="Close" aria-label="Close" onClick={this.closeSide} className="sf2-icon-x1 sf-popover-close side-panel-close op-icon d-md-none "></a>
<a title="Close" aria-label="Close" onClick={this.closeSide} className="sf2-icon-x1 sf-popover-close side-panel-close action-icon d-md-none "></a>
</div>
<div id="side-nav" className="wiki-side-nav" role="navigation">
<h3

View File

@@ -134,7 +134,7 @@ class Item extends Component {
}
let iconVisibility = this.state.showOpIcon ? '' : ' invisible';
let unshareIconClassName = 'unshare op-icon sf2-icon-x3' + iconVisibility;
let unshareIconClassName = 'unshare action-icon sf2-icon-x3' + iconVisibility;
return (
<tr onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>

View File

@@ -150,7 +150,7 @@ class Item extends Component {
}
let iconVisibility = this.state.showOpIcon ? '' : ' invisible';
let unshareIconClassName = 'unshare op-icon sf2-icon-x3' + iconVisibility;
let unshareIconClassName = 'unshare action-icon sf2-icon-x3' + iconVisibility;
if (showAdmin && this.permissions.indexOf('admin') === -1) {
this.permissions.splice(2, 0, 'admin'); // add a item after 'r' permission;

View File

@@ -146,8 +146,8 @@ class Item extends Component {
let { iconUrl, linkUrl } = this.getLinkParams();
let iconVisibility = this.state.showOpIcon ? '' : ' invisible';
let linkIconClassName = 'sf2-icon-link op-icon' + iconVisibility;
let deleteIconClassName = 'sf2-icon-delete op-icon' + iconVisibility;
let linkIconClassName = 'sf2-icon-link action-icon' + iconVisibility;
let deleteIconClassName = 'sf2-icon-delete action-icon' + iconVisibility;
return (
<tr onMouseOver={this.handleMouseOver} onMouseOut={this.handleMouseOut}>

View File

@@ -123,8 +123,8 @@ class Item extends Component {
let { iconUrl, uploadUrl } = this.getUploadParams();
let iconVisibility = this.state.showOpIcon ? '' : ' invisible';
let linkIconClassName = 'sf2-icon-link op-icon' + iconVisibility;
let deleteIconClassName = 'sf2-icon-delete op-icon' + iconVisibility;
let linkIconClassName = 'sf2-icon-link action-icon' + iconVisibility;
let deleteIconClassName = 'sf2-icon-delete action-icon' + iconVisibility;
return (
<tr onMouseOver={this.handleMouseOver} onMouseOut={this.handleMouseOut}>

View File

@@ -168,8 +168,8 @@ class Item extends Component {
data.url = `${siteRoot}#shared-libs/lib/${data.repo_id}/`;
let iconVisibility = this.state.showOpIcon ? '' : ' invisible';
let shareIconClassName = 'sf2-icon-share sf2-x repo-share-btn op-icon' + iconVisibility;
let leaveShareIconClassName = 'sf2-icon-delete sf2-x op-icon' + iconVisibility;
let shareIconClassName = 'op-icon sf2-icon-share repo-share-btn' + iconVisibility;
let leaveShareIconClassName = 'op-icon sf2-icon-delete' + iconVisibility;
const desktopItem = (
<tr onMouseOver={this.handleMouseOver} onMouseOut={this.handleMouseOut}>
@@ -181,7 +181,7 @@ class Item extends Component {
: ''}
<a href="#" className={leaveShareIconClassName} title={gettext("Leave Share")} onClick={this.leaveShare}></a>
</td>
<td>{Utils.formatSize({bytes: data.size})}</td>
<td>{Utils.bytesToSize(data.size)}</td>
<td title={moment(data.last_modified).format('llll')}>{moment(data.last_modified).fromNow()}</td>
<td title={data.owner_contact_email}>{data.owner_name}</td>
</tr>
@@ -193,7 +193,7 @@ class Item extends Component {
<td>
<Link to={`${siteRoot}library/${data.repo_id}/${data.repo_name}/`}>{data.repo_name}</Link><br />
<span className="item-meta-info" title={data.owner_contact_email}>{data.owner_name}</span>
<span className="item-meta-info">{Utils.formatSize({bytes: data.size})}</span>
<span className="item-meta-info">{Utils.bytesToSize(data.size)}</span>
<span className="item-meta-info" title={moment(data.last_modified).format('llll')}>{moment(data.last_modified).fromNow()}</span>
</td>
<td>

View File

@@ -160,7 +160,7 @@ class PublicSharedView extends React.Component {
<div className="operation">
<Dropdown isOpen={this.state.isCreateMenuShow} toggle={this.onAddRepoToggle}>
<DropdownToggle className='btn btn-secondary operation-item'>
<i className="fas fa-plus-square op-icon"></i>
<i className="fas fa-plus-square action-icon"></i>
{gettext('Add Library')}
</DropdownToggle>
<DropdownMenu>

View File

@@ -16,20 +16,20 @@ class Content extends Component {
const desktopThead = (
<thead>
<tr>
<th width="5%"></th>
<th width="4%"></th>
<th width="40%">{gettext('File Name')}</th>
<th width="32%">{gettext('Library')}</th>
<th width="18%">{gettext('Last Update')}</th>
<th width="5%"></th>
<th width="6%"></th>
</tr>
</thead>
);
const mobileThead = (
<thead>
<tr>
<th width="5%"></th>
<th width="4%"></th>
<th width="90%">{gettext('File Name')}</th>
<th width="5%"></th>
<th width="6%"></th>
</tr>
</thead>
);
@@ -159,7 +159,7 @@ class Item extends Component {
const data = this.props.data;
let opClasses = 'sf2-icon-delete unstar op-icon';
let opClasses = 'sf2-icon-x3 unstar action-icon';
opClasses += this.state.showOpIcon ? '' : ' invisible';
const desktopItem = (
@@ -206,7 +206,7 @@ class Item extends Component {
<span className="dirent-meta-info" dangerouslySetInnerHTML={{__html:data.mtime_relative}}></span>
</td>
<td>
<a href="#" className="sf2-icon-delete unstar op-icon" title={gettext('Unstar')} aria-label={gettext('Unstar')} onClick={this.handleClick}></a>
<a href="#" className="sf2-icon-delete unstar action-icon" title={gettext('Unstar')} aria-label={gettext('Unstar')} onClick={this.handleClick}></a>
</td>
</tr>
);

View File

@@ -180,7 +180,7 @@ class SidePanel extends Component {
<a href={siteRoot} id="logo">
<img src={mediaUrl + logoPath} title={siteTitle} alt="logo" width={logoWidth} height={logoHeight} />
</a>
<a title="Close" aria-label="Close" onClick={this.closeSide} className="sf2-icon-x1 sf-popover-close side-panel-close op-icon d-md-none "></a>
<a title="Close" aria-label="Close" onClick={this.closeSide} className="sf2-icon-x1 sf-popover-close side-panel-close action-icon d-md-none "></a>
</div>
<div id="side-nav" className="wiki-side-nav" role="navigation">
<h3

View File

@@ -126,7 +126,7 @@ class Wikis extends Component {
<Dropdown tag="div" className="btn btn-secondary operation-item" isOpen={this.state.isShowAddWikiMenu} toggle={this.onMenuToggle}>
<DropdownToggle
tag="i"
className="fa fa-plus-square op-icon"
className="fa fa-plus-square action-icon"
title={gettext('More Operations')}
data-toggle="dropdown"
aria-expanded={this.state.isShowAddWikiMenu}

View File

@@ -23,12 +23,13 @@
* sf-popover
* go-back
* top-logo
* table-list
* base-table
* table-item rename-component
* more-btn
* dropdown-menu
* empty-tip
* more-btn
* list-operation
* prompt-message
* file-tag
* mobile-menu
*/
/****** sf2-icon-xx ********/
@font-face {
@@ -123,14 +124,6 @@ ul,ol,li {
line-height: 1.5;
}
.text-left {
text-align: left;
}
.text-right {
text-align: right;
}
.a-simulate {
color: #eb8205 !important;
text-decoration: none;
@@ -142,20 +135,25 @@ ul,ol,li {
text-decoration: underline;
}
.flex-right {
justify-content: flex-end;
}
.sf-font {
color: #eb8205 !important;
text-decoration: none;
font-weight: normal;
}
.avatar-with-tooltip {
.cursor-pointer {
cursor: pointer;
}
.sf-dropdown-toggle {
vertical-align: middle;
font-style: normal;
font-size: 0.85rem;
line-height: 1;
cursor: pointer;
color: #888;
}
.user-select-none {
-moz-user-select:none;
-webkit-user-select:none;
@@ -189,10 +187,24 @@ ul,ol,li {
color: #fff;
}
.table-thread-hidden th {
padding: 0;
font-size: 0;
border: 0;
.panel-heading {
position: relative;
padding: .5rem 1rem;
width: 100%;
height: 2.5rem;
font-size: 1rem;
font-weight: normal;
line-height: 1.5;
text-align: center;
}
.side-nav-toggle { /* just for control side-panel */
margin-right:0.9375rem;
height: 1.875rem;
line-height: 1.875rem;
font-size:1.5rem;
color:#999;
cursor: pointer;
}
/* UI Widget */
@@ -280,27 +292,34 @@ ul,ol,li {
}
/** op-icon **/
.op-icon {
font-size:20px;
line-height:1;
color:#888;
cursor:pointer;
margin-right:3px;
vertical-align:middle;
}
.op-icon:focus,
.op-icon:hover {
color: #333;
text-decoration:none;
.op-icon,
.action-icon {
margin-right: 0.5rem;
font-size: 1.25rem;
font-style: normal;
line-height: 1;
cursor: pointer;
vertical-align: middle;
}
.op-icon.sf2-x,
.op-icon.sf2-x:hover {
color:#f89a68;
.op-icon {
color: #f89a68;
}
.op-icon.sf2-x:hover,
.op-icon.sf2-x:focus {
border-bottom: 0.125rem solid #f89a68;;
.op-icon:focus,
.op-icon:hover {
padding-bottom: 0.125rem;
border-bottom: 0.125rem solid #f89a68;
}
.action-icon {
color:#888;
}
.action-icon:focus,
.action-icon:hover {
color: #333;
text-decoration: none;
}
/** Account info **/
@@ -342,7 +361,6 @@ ul,ol,li {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.account-popup {
@@ -741,7 +759,7 @@ a.sf-popover-item:hover {
}
@media (max-width: 767px) {
.side-panel-top {
border-right:1px solid #eee;
border-right: 1px solid #eee;
}
}
.side-panel-close {
@@ -755,35 +773,14 @@ a.sf-popover-item:hover {
flex-shrink:0;
}
/* begin top logo */
/* top logo */
.top-logo {
display: flex;
justify-content: space-between;
flex: 1;
}
/* end top logo */
.panel-heading {
position: relative;
padding: .5rem 1rem;
width: 100%;
height: 2.5rem;
font-size: 1rem;
font-weight: normal;
line-height: 1.5;
text-align: center;
}
.side-nav-toggle {
margin-right:0.9375rem;
height: 1.875rem;
line-height: 1.875rem;
font-size:1.5rem;
color:#999;
cursor: pointer;
}
/* begin path navigation */
/* path navigation */
.path-container { /* for the real path */
font-size: 1rem;
word-break: break-all;
@@ -801,59 +798,53 @@ a.sf-popover-item:hover {
cursor: pointer;
text-decoration: underline !important;
}
/* end path navigation */
/* begin main table list style */
/* base table style */
table {
width: 100%;
table-layout: fixed;
}
table th, table td {
padding: 5px 3px;
table tr {
height: 2.1875rem;
border-bottom: 1px solid #eee;
}
table th, table td {
padding: 0.3125rem 0.1875rem;
}
table th {
text-align: left;
font-weight: normal;
font-size: 13px;
font-size: 0.8125rem;
line-height: 1.6;
color: #9c9c9c;
}
table td {
color: #333;
font-size: 14px;
font-size: 0.875rem;
word-break: break-all;
}
table .select,
table .star,
table .icon {
position: relative;
text-align: center;
}
table .icon img {
table td img {
width: 1.5rem;
height: 1.5rem;
}
table .dir-icon {
position: relative;
.table-thread-hidden th { /* hide table th */
padding: 0;
border: 0;
font-size: 0;
}
table .star {
cursor: pointer;
.tr-highlight {
background-color: #f8f8f8;
}
table .star .empty {
color: #d0d0d0;
}
table .name {
line-height: 1.5rem;
}
table .rename-container input {
/* table-item reanme-component */
.rename-container input {
box-sizing: content-box;
padding: 2px 3px;
width: 15rem;
@@ -865,14 +856,14 @@ table .rename-container input {
border: 1px solid #ccc;
}
table .rename-container input:focus {
.rename-container input:focus {
background-color: #fff;
border-color: #1991eb;
outline: 0;
box-shadow: 0 0 0 2px rgba(70, 127, 207, 0.25);
}
table .rename-container button {
.rename-container button {
margin-left: 0.25rem;
padding: 5px 6px;
font-size: 1rem;
@@ -881,29 +872,30 @@ table .rename-container button {
min-width: 0;
}
table .rename-container .confirm {
.rename-container .confirm {
color: green;
}
table .dir-icon .locked {
position: absolute;
width: 1rem;
height: 1rem;
top: 50%;
left: 50%;
}
table .menu-toggle {
/* table-item loading-more-data */
.list-show-more {
padding: 0.25rem 0.75rem;
line-height: 2rem;
text-align: center;
color: #eb8205;
cursor: pointer;
}
.tr-highlight {
background-color: #f8f8f8;
.list-show-more:hover {
background-color: #eee;
}
/* end table list style */
/* begin dropdown-menu style */
.list-show-more .more-message {
font-size: 0.875rem;
color: #888;
text-decoration: underline;
}
/* dropdown-menu style */
.dropdown-menu {
min-width: 8rem;
}
@@ -911,9 +903,7 @@ table .menu-toggle {
cursor: pointer;
}
/* end dropdown-menu style */
/* begin tip */
/* empty-tip */
.empty-tip {
margin: auto 1rem;
padding: 30px 40px;
@@ -933,88 +923,8 @@ table .menu-toggle {
.err-message h2{
color: red;
}
/* end tip */
/* begin more component */
.list-show-more {
padding: 0.25rem 0.75rem;
line-height: 2rem;
text-align: center;
color: #eb8205;
cursor: pointer;
}
.list-show-more:hover {
background-color: #eee;
}
.list-show-more .more-message {
font-size: 0.875rem;
color: #888;
text-decoration: underline;
}
/* end more component */
/* begin operation menu */
.operations {
display: flex;
}
.operations .operation-group {
list-style: none;
}
.operation-group .operation-group-item {
display: inline-block;
color: #f89a68;
margin-right: 0.5rem;
}
.operation-group-item i {
font-style: normal;
font-size: 1.25rem;
line-height: 1;
cursor: pointer;
vertical-align: middle;
}
.operation-group-item i:hover {
padding-bottom: 0.125rem;
border-bottom: 0.125rem solid #f89a68;
}
.operation-group-item .sf-dropdown-toggle {
font-size: 0.85rem;
color: #888;
}
.operation-group-item .sf-dropdown-toggle:hover {
text-decoration: none;
}
/* end operaton menu */
.cur-view-path .tab-tabs-nav {
font-size:15px;
list-style: none;
}
.tab-tabs-nav .tab {
float:left;
border:0;
background:none;
}
.tab-tabs-nav .tab .a {
color:#8A948F;
font-weight:normal;
padding:.3em 0;
margin-right:0.6em;
}
.tab-tabs-nav .ui-state-active .a {
color:#DD4B39;
border-bottom:2px solid #DD4B39;
}
.tab-tabs-nav .tab .a:hover {
color:#DD4B39;
}
.cur-view-path .tab-tabs-nav .ui-state-active .a,
.cur-view-path .tab-tabs-nav .a:hover {
color:#eb8205;
text-decoration:none;
border-bottom-color:#eb8205;
}
/* begin file-tag */
/* file-tag */
.tag-list {
position: relative;
justify-content: flex-end;
@@ -1042,46 +952,12 @@ table .menu-toggle {
border-radius: 50%;
}
/* end file-tag */
.dirent-item.tag-list {
display: flex;
align-items: center;
width: max-content;
}
.item-meta-info {
display: inline-block;
margin-right: 8px;
font-size: 12px;
color: #666;
}
.item-operation-menu-toggle-icon {
display: inline-block;
margin-top: 4px;
font-size: 12px;
}
.mobile-operation-menu-bg-layer {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
background: #000;
opacity: 0.1;
z-index: 3;
}
.mobile-operation-menu {
position: fixed;
left: 0;
right: 0;
bottom: 0;
padding: .5em 0;
background: #fff;
text-align: center;
z-index: 4;
}
/* react select-module */
.select-module {
font-size: 1rem;
@@ -1094,3 +970,33 @@ table .menu-toggle {
.select-module.select-module-name {
margin-left: 0.5rem;
}
/* mobile menu */
.item-meta-info {
display: inline-block;
margin-right: 8px;
font-size: 12px;
color: #666;
}
.mobile-operation-menu-bg-layer {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
background: #000;
opacity: 0.1;
z-index: 3;
}
.mobile-operation-menu {
position: fixed;
left: 0;
right: 0;
bottom: 0;
padding: .5em 0;
background: #fff;
text-align: center;
z-index: 4;
}