mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-08 18:30:53 +00:00
[a11y] added 'keyboard access' for 'dir view - dirent' & fixed bugs
This commit is contained in:
@@ -9,10 +9,6 @@ const propTypes = {
|
|||||||
|
|
||||||
class AboutDialog extends React.Component {
|
class AboutDialog extends React.Component {
|
||||||
|
|
||||||
toggle = () => {
|
|
||||||
this.props.onCloseAboutDialog();
|
|
||||||
}
|
|
||||||
|
|
||||||
renderExternalAboutLinks = () => {
|
renderExternalAboutLinks = () => {
|
||||||
if (additionalAboutDialogLinks && (typeof additionalAboutDialogLinks) === 'object') {
|
if (additionalAboutDialogLinks && (typeof additionalAboutDialogLinks) === 'object') {
|
||||||
let keys = Object.keys(additionalAboutDialogLinks);
|
let keys = Object.keys(additionalAboutDialogLinks);
|
||||||
@@ -26,21 +22,22 @@ class AboutDialog extends React.Component {
|
|||||||
render() {
|
render() {
|
||||||
|
|
||||||
let href = lang === lang == 'zh-cn' ? 'http://seafile.com/about/' : 'http://seafile.com/en/about/';
|
let href = lang === lang == 'zh-cn' ? 'http://seafile.com/about/' : 'http://seafile.com/en/about/';
|
||||||
|
const { onCloseAboutDialog: toggleDialog } = this.props;
|
||||||
|
|
||||||
if (aboutDialogCustomHtml) {
|
if (aboutDialogCustomHtml) {
|
||||||
return (
|
return (
|
||||||
<Modal isOpen={true} toggle={this.toggle}>
|
<Modal isOpen={true} toggle={toggleDialog}>
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
<button type="button" className="close" onClick={this.toggle}><span aria-hidden="true">×</span></button>
|
<button type="button" className="close" onClick={toggleDialog}><span aria-hidden="true">×</span></button>
|
||||||
<div className="about-content" dangerouslySetInnerHTML={{__html: aboutDialogCustomHtml}}></div>
|
<div className="about-content" dangerouslySetInnerHTML={{__html: aboutDialogCustomHtml}}></div>
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<Modal isOpen={true} toggle={this.toggle}>
|
<Modal isOpen={true} toggle={toggleDialog}>
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
<button type="button" className="close" onClick={this.toggle}><span aria-hidden="true">×</span></button>
|
<button type="button" className="close" onClick={toggleDialog}><span aria-hidden="true">×</span></button>
|
||||||
<div className="about-content">
|
<div className="about-content">
|
||||||
<p><img src={mediaUrl + logoPath} height={logoHeight} width={logoWidth} title={siteTitle} alt="logo" /></p>
|
<p><img src={mediaUrl + logoPath} height={logoHeight} width={logoWidth} title={siteTitle} alt="logo" /></p>
|
||||||
<p>{gettext('Server Version: ')}{seafileVersion}<br />© {(new Date()).getFullYear()} {gettext('Seafile')}</p>
|
<p>{gettext('Server Version: ')}{seafileVersion}<br />© {(new Date()).getFullYear()} {gettext('Seafile')}</p>
|
||||||
|
@@ -26,10 +26,6 @@ class DeleteRepoDialog extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toggle = () => {
|
|
||||||
this.props.toggle();
|
|
||||||
}
|
|
||||||
|
|
||||||
onDeleteRepo = () => {
|
onDeleteRepo = () => {
|
||||||
this.setState({isRequestSended: true}, () => {
|
this.setState({isRequestSended: true}, () => {
|
||||||
this.props.onDeleteRepo(this.props.repo);
|
this.props.onDeleteRepo(this.props.repo);
|
||||||
@@ -44,14 +40,16 @@ class DeleteRepoDialog extends Component {
|
|||||||
let message = gettext('Are you sure you want to delete %s ?');
|
let message = gettext('Are you sure you want to delete %s ?');
|
||||||
message = message.replace('%s', repoName);
|
message = message.replace('%s', repoName);
|
||||||
|
|
||||||
|
const { toggle: toggleDialog } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal isOpen={true} toggle={this.toggle}>
|
<Modal isOpen={true} toggle={toggleDialog}>
|
||||||
<ModalHeader toggle={this.toggle}>{gettext('Delete Library')}</ModalHeader>
|
<ModalHeader toggle={toggleDialog}>{gettext('Delete Library')}</ModalHeader>
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
<p dangerouslySetInnerHTML={{__html: message}}></p>
|
<p dangerouslySetInnerHTML={{__html: message}}></p>
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
<ModalFooter>
|
<ModalFooter>
|
||||||
<Button color="secondary" onClick={this.toggle}>{gettext('Cancel')}</Button>
|
<Button color="secondary" onClick={toggleDialog}>{gettext('Cancel')}</Button>
|
||||||
<Button color="primary" disabled={isRequestSended} onClick={this.onDeleteRepo}>{gettext('Delete')}</Button>
|
<Button color="primary" disabled={isRequestSended} onClick={this.onDeleteRepo}>{gettext('Delete')}</Button>
|
||||||
</ModalFooter>
|
</ModalFooter>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
@@ -154,11 +154,13 @@ class DirentListItem extends React.Component {
|
|||||||
this.props.onItemSelected(this.props.dirent);
|
this.props.onItemSelected(this.props.dirent);
|
||||||
}
|
}
|
||||||
|
|
||||||
onItemStarred = () => {
|
onItemStarred = (e) => {
|
||||||
let dirent = this.props.dirent;
|
let dirent = this.props.dirent;
|
||||||
let repoID = this.props.repoID;
|
let repoID = this.props.repoID;
|
||||||
let filePath = this.getDirentPath(dirent);
|
let filePath = this.getDirentPath(dirent);
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
if (dirent.starred) {
|
if (dirent.starred) {
|
||||||
seafileAPI.unstarItem(repoID, filePath).then(() => {
|
seafileAPI.unstarItem(repoID, filePath).then(() => {
|
||||||
this.props.updateDirent(this.props.dirent, 'starred', false);
|
this.props.updateDirent(this.props.dirent, 'starred', false);
|
||||||
@@ -209,11 +211,13 @@ class DirentListItem extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onItemDelete = (e) => {
|
onItemDelete = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
e.nativeEvent.stopImmediatePropagation(); //for document event
|
e.nativeEvent.stopImmediatePropagation(); //for document event
|
||||||
this.props.onItemDelete(this.props.dirent);
|
this.props.onItemDelete(this.props.dirent);
|
||||||
}
|
}
|
||||||
|
|
||||||
onItemShare = (e) => {
|
onItemShare = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
e.nativeEvent.stopImmediatePropagation(); //for document event
|
e.nativeEvent.stopImmediatePropagation(); //for document event
|
||||||
this.setState({isShareDialogShow: !this.state.isShareDialogShow});
|
this.setState({isShareDialogShow: !this.state.isShareDialogShow});
|
||||||
}
|
}
|
||||||
@@ -382,6 +386,7 @@ class DirentListItem extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onItemDownload = (e) => {
|
onItemDownload = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
e.nativeEvent.stopImmediatePropagation();
|
e.nativeEvent.stopImmediatePropagation();
|
||||||
let dirent = this.props.dirent;
|
let dirent = this.props.dirent;
|
||||||
let repoID = this.props.repoID;
|
let repoID = this.props.repoID;
|
||||||
@@ -570,88 +575,48 @@ class DirentListItem extends React.Component {
|
|||||||
<Fragment>
|
<Fragment>
|
||||||
{this.state.isOperationShow && !dirent.isSelected &&
|
{this.state.isOperationShow && !dirent.isSelected &&
|
||||||
<div className="operations">
|
<div className="operations">
|
||||||
<ul className="operation-group">
|
{(dirent.permission === 'rw' || dirent.permission === 'r' || (isCustomPermission && canDownload)) && (
|
||||||
{(dirent.permission === 'rw' || dirent.permission === 'r') && (
|
<a href="#" className="op-icon sf2-icon-download" title={gettext('Download')} role="button" aria-label={gettext('Download')} onClick={this.onItemDownload}></a>
|
||||||
<li className="operation-group-item">
|
)}
|
||||||
<i className="op-icon sf2-icon-download" title={gettext('Download')} onClick={this.onItemDownload}></i>
|
{showShareBtn && (
|
||||||
</li>
|
<a href="#" className="op-icon sf2-icon-share" title={gettext('Share')} role="button" aria-label={gettext('Share')} onClick={this.onItemShare}></a>
|
||||||
)}
|
)}
|
||||||
{(isCustomPermission && canDownload) && (
|
{(dirent.permission === 'rw' || (isCustomPermission && canDelete)) && (
|
||||||
<li className="operation-group-item">
|
<a href="#" className="op-icon sf2-icon-delete" title={gettext('Delete')} role="button" aria-label={gettext('Delete')} onClick={this.onItemDelete}></a>
|
||||||
<i className="op-icon sf2-icon-download" title={gettext('Download')} onClick={this.onItemDownload}></i>
|
)}
|
||||||
</li>
|
<ItemDropdownMenu
|
||||||
)}
|
item={this.props.dirent}
|
||||||
{showShareBtn && (
|
toggleClass={'sf2-icon-caret-down'}
|
||||||
<li className="operation-group-item">
|
isHandleContextMenuEvent={true}
|
||||||
<i className="op-icon sf2-icon-share" title={gettext('Share')} onClick={this.onItemShare}></i>
|
getMenuList={this.props.getDirentItemMenuList}
|
||||||
</li>
|
onMenuItemClick={this.onMenuItemClick}
|
||||||
)}
|
unfreezeItem={this.unfreezeItem}
|
||||||
{dirent.permission === 'rw' && (
|
freezeItem={this.props.freezeItem}
|
||||||
<li className="operation-group-item">
|
/>
|
||||||
<i className="op-icon sf2-icon-delete" title={gettext('Delete')} onClick={this.onItemDelete}></i>
|
|
||||||
</li>
|
|
||||||
)}
|
|
||||||
{(isCustomPermission && canDelete) && (
|
|
||||||
<li className="operation-group-item">
|
|
||||||
<i className="op-icon sf2-icon-delete" title={gettext('Delete')} onClick={this.onItemDelete}></i>
|
|
||||||
</li>
|
|
||||||
)}
|
|
||||||
<li className="operation-group-item">
|
|
||||||
<ItemDropdownMenu
|
|
||||||
item={this.props.dirent}
|
|
||||||
toggleClass={'sf2-icon-caret-down'}
|
|
||||||
isHandleContextMenuEvent={true}
|
|
||||||
getMenuList={this.props.getDirentItemMenuList}
|
|
||||||
onMenuItemClick={this.onMenuItemClick}
|
|
||||||
unfreezeItem={this.unfreezeItem}
|
|
||||||
freezeItem={this.props.freezeItem}
|
|
||||||
/>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</Fragment> :
|
</Fragment> :
|
||||||
<Fragment>
|
<Fragment>
|
||||||
{this.state.isOperationShow &&
|
{this.state.isOperationShow &&
|
||||||
<div className="operations">
|
<div className="operations">
|
||||||
<ul className="operation-group">
|
{(dirent.permission === 'rw' || dirent.permission === 'r' || (isCustomPermission && canDownload)) && (
|
||||||
{(dirent.permission === 'rw' || dirent.permission === 'r') && (
|
<a href="#" className="op-icon sf2-icon-download" title={gettext('Download')} role="button" aria-label={gettext('Download')} onClick={this.onItemDownload}></a>
|
||||||
<li className="operation-group-item">
|
)}
|
||||||
<i className="op-icon sf2-icon-download" title={gettext('Download')} onClick={this.onItemDownload}></i>
|
{showShareBtn && (
|
||||||
</li>
|
<a href="#" className="op-icon sf2-icon-share" title={gettext('Share')} role="button" aria-label={gettext('Share')} onClick={this.onItemShare}></a>
|
||||||
)}
|
)}
|
||||||
{(isCustomPermission && canDownload) && (
|
{(dirent.permission === 'rw' || (isCustomPermission && canDelete)) && (
|
||||||
<li className="operation-group-item">
|
<a href="#" className="op-icon sf2-icon-delete" title={gettext('Delete')} role="button" aria-label={gettext('Delete')} onClick={this.onItemDelete}></a>
|
||||||
<i className="op-icon sf2-icon-download" title={gettext('Download')} onClick={this.onItemDownload}></i>
|
)}
|
||||||
</li>
|
<ItemDropdownMenu
|
||||||
)}
|
item={this.props.dirent}
|
||||||
{showShareBtn && (
|
toggleClass={'sf2-icon-caret-down'}
|
||||||
<li className="operation-group-item">
|
isHandleContextMenuEvent={true}
|
||||||
<i className="op-icon sf2-icon-share" title={gettext('Share')} onClick={this.onItemShare}></i>
|
getMenuList={this.props.getDirentItemMenuList}
|
||||||
</li>
|
onMenuItemClick={this.onMenuItemClick}
|
||||||
)}
|
unfreezeItem={this.unfreezeItem}
|
||||||
{(dirent.permission === 'rw') && (
|
freezeItem={this.props.freezeItem}
|
||||||
<li className="operation-group-item">
|
/>
|
||||||
<i className="op-icon sf2-icon-delete" title={gettext('Delete')} onClick={this.onItemDelete}></i>
|
|
||||||
</li>
|
|
||||||
)}
|
|
||||||
{(isCustomPermission && canDelete) && (
|
|
||||||
<li className="operation-group-item">
|
|
||||||
<i className="op-icon sf2-icon-delete" title={gettext('Delete')} onClick={this.onItemDelete}></i>
|
|
||||||
</li>
|
|
||||||
)}
|
|
||||||
<li className="operation-group-item">
|
|
||||||
<ItemDropdownMenu
|
|
||||||
item={this.props.dirent}
|
|
||||||
toggleClass={'sf2-icon-caret-down'}
|
|
||||||
isHandleContextMenuEvent={true}
|
|
||||||
getMenuList={this.props.getDirentItemMenuList}
|
|
||||||
onMenuItemClick={this.onMenuItemClick}
|
|
||||||
unfreezeItem={this.unfreezeItem}
|
|
||||||
freezeItem={this.props.freezeItem}
|
|
||||||
/>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
@@ -690,6 +655,7 @@ class DirentListItem extends React.Component {
|
|||||||
<tr
|
<tr
|
||||||
className={trClass}
|
className={trClass}
|
||||||
draggable={this.canDrag}
|
draggable={this.canDrag}
|
||||||
|
onFocus={this.onMouseEnter}
|
||||||
onMouseEnter={this.onMouseEnter}
|
onMouseEnter={this.onMouseEnter}
|
||||||
onMouseOver={this.onMouseOver}
|
onMouseOver={this.onMouseOver}
|
||||||
onMouseLeave={this.onMouseLeave}
|
onMouseLeave={this.onMouseLeave}
|
||||||
@@ -706,8 +672,11 @@ class DirentListItem extends React.Component {
|
|||||||
<input type="checkbox" className="vam" onChange={this.onItemSelected} checked={dirent.isSelected}/>
|
<input type="checkbox" className="vam" onChange={this.onItemSelected} checked={dirent.isSelected}/>
|
||||||
</td>
|
</td>
|
||||||
<td className="pl10">
|
<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 !== undefined && dirent.starred && <i className="fas fa-star cursor-pointer" onClick={this.onItemStarred}></i>}
|
<a href="#" role="button" aria-label={dirent.starred ? gettext('Unstar') : gettext('Star')} onClick={this.onItemStarred}>
|
||||||
|
<i className={`fa-star ${dirent.starred ? 'fas' : 'far star-empty'}`}></i>
|
||||||
|
</a>
|
||||||
|
}
|
||||||
</td>
|
</td>
|
||||||
<td className="pl10">
|
<td className="pl10">
|
||||||
<div className="dir-icon">
|
<div className="dir-icon">
|
||||||
@@ -796,6 +765,8 @@ class DirentListItem extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<DropdownItem className="mobile-menu-item" key={index} data-op={item.key} onClick={this.onMobileMenuItemClick}>{item.value}</DropdownItem>
|
<DropdownItem className="mobile-menu-item" key={index} data-op={item.key} onClick={this.onMobileMenuItemClick}>{item.value}</DropdownItem>
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
@@ -589,7 +589,7 @@ class DirentListView extends React.Component {
|
|||||||
<thead onMouseDown={this.onThreadMouseDown} onContextMenu={this.onThreadContextMenu}>
|
<thead onMouseDown={this.onThreadMouseDown} onContextMenu={this.onThreadContextMenu}>
|
||||||
<tr>
|
<tr>
|
||||||
<th width="3%" className="pl10">
|
<th width="3%" className="pl10">
|
||||||
<input type="checkbox" className="vam" onChange={this.props.onAllItemSelected} checked={this.props.isAllItemSelected}/>
|
<input type="checkbox" className="vam" onChange={this.props.onAllItemSelected} checked={this.props.isAllItemSelected} />
|
||||||
</th>
|
</th>
|
||||||
<th width="3%" className="pl10">{/*icon */}</th>
|
<th width="3%" className="pl10">{/*icon */}</th>
|
||||||
<th width="5%" className="pl10">{/*star */}</th>
|
<th width="5%" className="pl10">{/*star */}</th>
|
||||||
|
@@ -146,6 +146,8 @@ class ItemDropdownMenu extends React.Component {
|
|||||||
<Dropdown isOpen={this.state.isItemMenuShow} toggle={this.onDropdownToggleClick}>
|
<Dropdown isOpen={this.state.isItemMenuShow} toggle={this.onDropdownToggleClick}>
|
||||||
<DropdownToggle
|
<DropdownToggle
|
||||||
tag={tagName || 'i'}
|
tag={tagName || 'i'}
|
||||||
|
role="button"
|
||||||
|
tabIndex="0"
|
||||||
className={toggleClass}
|
className={toggleClass}
|
||||||
title={gettext('More Operations')}
|
title={gettext('More Operations')}
|
||||||
data-toggle="dropdown"
|
data-toggle="dropdown"
|
||||||
|
@@ -13,9 +13,7 @@ class SideNavFooter extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onAboutDialogToggle = (e) => {
|
onAboutDialogToggle = (e) => {
|
||||||
if (e) {
|
e.preventDefault();
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
this.setState({isAboutDialogShow: !this.state.isAboutDialogShow});
|
this.setState({isAboutDialogShow: !this.state.isAboutDialogShow});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,15 +1,6 @@
|
|||||||
.tr-drop-effect {
|
.tr-drop-effect {
|
||||||
background-color: #f8f8f8;
|
background-color: #f8f8f8;
|
||||||
}
|
}
|
||||||
.operations {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
.operations .operation-group {
|
|
||||||
list-style: none;
|
|
||||||
}
|
|
||||||
.operation-group .operation-group-item {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.star-empty {
|
.star-empty {
|
||||||
color: #d0d0d0;
|
color: #d0d0d0;
|
||||||
@@ -31,4 +22,4 @@
|
|||||||
|
|
||||||
.tag-list-title {
|
.tag-list-title {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
@@ -146,13 +146,15 @@ class MylibRepoMenu extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<Dropdown isOpen={this.state.isItemMenuShow} toggle={this.toggleOperationMenu}>
|
<Dropdown isOpen={this.state.isItemMenuShow} toggle={this.toggleOperationMenu}>
|
||||||
<DropdownToggle
|
<DropdownToggle
|
||||||
className="sf-dropdown-toggle sf2-icon-caret-down border-0 p-0"
|
tag="i"
|
||||||
|
role="button"
|
||||||
|
tabIndex="0"
|
||||||
|
className="sf-dropdown-toggle sf2-icon-caret-down"
|
||||||
title={gettext('More Operations')}
|
title={gettext('More Operations')}
|
||||||
|
aria-label={gettext('More Operations')}
|
||||||
onClick={this.onDropdownToggleClick}
|
onClick={this.onDropdownToggleClick}
|
||||||
onKeyDown={this.onDropdownToggleKeyDown}
|
onKeyDown={this.onDropdownToggleKeyDown}
|
||||||
data-toggle="dropdown"
|
data-toggle="dropdown"
|
||||||
aria-haspopup={true}
|
|
||||||
style={{'minWidth': '0'}}
|
|
||||||
/>
|
/>
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
{operations.map((item, index)=> {
|
{operations.map((item, index)=> {
|
||||||
|
Reference in New Issue
Block a user