mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-27 15:54:39 +00:00
Change share link dialog UI (#7881)
* 01 Add qr-code in share link item * 02 Show access scope and password in share list * 03 optimise style
This commit is contained in:
@@ -3,6 +3,8 @@ import PropTypes from 'prop-types';
|
|||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import copy from 'copy-to-clipboard';
|
import copy from 'copy-to-clipboard';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
import { QRCodeSVG } from 'qrcode.react';
|
||||||
|
import { Popover, PopoverBody } from 'reactstrap';
|
||||||
import toaster from '../toast';
|
import toaster from '../toast';
|
||||||
import { gettext } from '../../utils/constants';
|
import { gettext } from '../../utils/constants';
|
||||||
import { Utils } from '../../utils/utils';
|
import { Utils } from '../../utils/utils';
|
||||||
@@ -22,10 +24,31 @@ class LinkItem extends React.Component {
|
|||||||
this.state = {
|
this.state = {
|
||||||
isHighlighted: false,
|
isHighlighted: false,
|
||||||
isItemOpVisible: false,
|
isItemOpVisible: false,
|
||||||
isDeleteShareLinkDialogOpen: false
|
isDeleteShareLinkDialogOpen: false,
|
||||||
|
isQRCodePopoverOpen: false
|
||||||
};
|
};
|
||||||
|
this.qrCodeBtn = null;
|
||||||
|
this.popoverContainerRef = React.createRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
document.addEventListener('mousedown', this.handleClickOutside);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
document.removeEventListener('mousedown', this.handleClickOutside);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleClickOutside = (event) => {
|
||||||
|
if (this.state.isQRCodePopoverOpen && this.popoverContainerRef.current &&
|
||||||
|
!this.popoverContainerRef.current.contains(event.target) &&
|
||||||
|
this.qrCodeBtn && !this.qrCodeBtn.contains(event.target)) {
|
||||||
|
this.setState({
|
||||||
|
isQRCodePopoverOpen: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
onMouseOver = () => {
|
onMouseOver = () => {
|
||||||
this.setState({
|
this.setState({
|
||||||
isHighlighted: true,
|
isHighlighted: true,
|
||||||
@@ -81,8 +104,33 @@ class LinkItem extends React.Component {
|
|||||||
this.props.deleteLink(item.token);
|
this.props.deleteLink(item.token);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
toggleQRCodePopover = () => {
|
||||||
|
this.setState({
|
||||||
|
isQRCodePopoverOpen: !this.state.isQRCodePopoverOpen
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onQRCodeIconClicked = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
this.toggleQRCodePopover();
|
||||||
|
};
|
||||||
|
|
||||||
|
translateScope = (scope) => {
|
||||||
|
if (scope === 'all_users') {
|
||||||
|
return gettext('Anyone with the link');
|
||||||
|
}
|
||||||
|
if (scope === 'specific_users') {
|
||||||
|
return gettext('Specific users in the team');
|
||||||
|
}
|
||||||
|
if (scope === 'specific_emails') {
|
||||||
|
return gettext('Specific people with email address');
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { isHighlighted, isItemOpVisible } = this.state;
|
const { isHighlighted, isItemOpVisible, isQRCodePopoverOpen } = this.state;
|
||||||
const { item } = this.props;
|
const { item } = this.props;
|
||||||
const { isSelected = false, permissions, link, expire_date } = item;
|
const { isSelected = false, permissions, link, expire_date } = item;
|
||||||
const currentPermission = Utils.getShareLinkPermissionStr(permissions);
|
const currentPermission = Utils.getShareLinkPermissionStr(permissions);
|
||||||
@@ -113,12 +161,25 @@ class LinkItem extends React.Component {
|
|||||||
<td>
|
<td>
|
||||||
{permissions && Utils.getShareLinkPermissionObject(currentPermission).text}
|
{permissions && Utils.getShareLinkPermissionObject(currentPermission).text}
|
||||||
</td>
|
</td>
|
||||||
|
<td>{this.translateScope(item.user_scope)}</td>
|
||||||
<td>
|
<td>
|
||||||
{expire_date ? dayjs(expire_date).format('YYYY-MM-DD HH:mm') : '--'}
|
{expire_date ? dayjs(expire_date).format('YYYY-MM-DD HH:mm') : '--'}
|
||||||
</td>
|
</td>
|
||||||
|
<td>{item.password && <i className='sf2-icon-tick'></i>}</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="#" role="button" onClick={this.onCopyIconClicked} className={`sf3-font sf3-font-copy1 op-icon ${isItemOpVisible ? '' : 'invisible'}`} title={gettext('Copy')} aria-label={gettext('Copy')}></a>
|
<a href="#" role="button" onClick={this.onCopyIconClicked} className={`sf3-font sf3-font-copy1 op-icon ${isItemOpVisible ? '' : 'invisible'}`} title={gettext('Copy')} aria-label={gettext('Copy')}></a>
|
||||||
<a href="#" role="button" onClick={this.onDeleteIconClicked} className={`sf3-font-delete1 sf3-font op-icon ${isItemOpVisible ? '' : 'invisible'}`} title={gettext('Delete')} aria-label={gettext('Delete')}></a>
|
<a href="#" role="button" onClick={this.onDeleteIconClicked} className={`sf3-font-delete1 sf3-font op-icon ${isItemOpVisible ? '' : 'invisible'}`} title={gettext('Delete')} aria-label={gettext('Delete')}></a>
|
||||||
|
<a href="#" role="button" ref={ref => this.qrCodeBtn = ref} onClick={this.onQRCodeIconClicked} className={`sf3-font sf3-font-qr-code op-icon ${isItemOpVisible ? '' : 'invisible'}`} title={gettext('QR Code')} aria-label={gettext('QR Code')}></a>
|
||||||
|
{this.qrCodeBtn && (
|
||||||
|
<div ref={this.popoverContainerRef}>
|
||||||
|
<Popover className="link-item-qrcode-popover" placement="bottom" isOpen={isQRCodePopoverOpen} target={this.qrCodeBtn}>
|
||||||
|
<PopoverBody>
|
||||||
|
<QRCodeSVG value={link} size={128} />
|
||||||
|
<p className="link-item-qrcode-tip">{gettext('Scan the QR code to view the shared content directly')}</p>
|
||||||
|
</PopoverBody>
|
||||||
|
</Popover>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{this.state.isDeleteShareLinkDialogOpen && (
|
{this.state.isDeleteShareLinkDialogOpen && (
|
||||||
|
@@ -79,12 +79,14 @@ class LinkList extends React.Component {
|
|||||||
<table className="table-place-header">
|
<table className="table-place-header">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th width="5%" className="text-center">
|
<th width="3%" className="text-center">
|
||||||
<input type="checkbox" checked={isAllLinksSelected} className="vam" onChange={this.toggleSelectAllLinks} />
|
<input type="checkbox" checked={isAllLinksSelected} className="vam" onChange={this.toggleSelectAllLinks} />
|
||||||
</th>
|
</th>
|
||||||
<th width="26%">{gettext('Link')}</th>
|
<th width="18%">{gettext('Link')}</th>
|
||||||
<th width="30%">{gettext('Permission')}</th>
|
<th width="25%">{gettext('Permission')}</th>
|
||||||
<th width="25%">{gettext('Expiration')}</th>
|
<th width="20%">{gettext('Access scope')}</th>
|
||||||
|
<th width="20%">{gettext('Expiration')}</th>
|
||||||
|
<th width="11%">{gettext('Password')}</th>
|
||||||
<th width="14%"></th>
|
<th width="14%"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@@ -93,10 +95,12 @@ class LinkList extends React.Component {
|
|||||||
<table className="table-real-content table-thead-hidden">
|
<table className="table-real-content table-thead-hidden">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th width="5%" className="text-center"></th>
|
<th width="3%" className="text-center"></th>
|
||||||
<th width="26%">{gettext('Link')}</th>
|
<th width="18%">{gettext('Link')}</th>
|
||||||
<th width="30%">{gettext('Permission')}</th>
|
<th width="25%">{gettext('Permission')}</th>
|
||||||
<th width="25%">{gettext('Expiration')}</th>
|
<th width="20%">{gettext('Access scope')}</th>
|
||||||
|
<th width="20%">{gettext('Expiration')}</th>
|
||||||
|
<th width="11%">{gettext('Password')}</th>
|
||||||
<th width="14%"></th>
|
<th width="14%"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.share-dialog-content .share-dialog-side {
|
.share-dialog-content .share-dialog-side {
|
||||||
flex-basis: 22%;
|
flex-basis: 18%;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border-bottom: 1px solid #eee;
|
border-bottom: 1px solid #eee;
|
||||||
}
|
}
|
||||||
@@ -69,7 +69,7 @@
|
|||||||
|
|
||||||
.share-dialog-content .share-dialog-main {
|
.share-dialog-content .share-dialog-main {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-basis: 78%;
|
flex-basis: 82%;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,3 +210,11 @@ input.expire-input {
|
|||||||
max-height: 350px;
|
max-height: 350px;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.link-item-qrcode-popover .link-item-qrcode-tip {
|
||||||
|
margin: 0;
|
||||||
|
margin-top: 0.25rem;
|
||||||
|
text-align: center;
|
||||||
|
max-width: 128px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user