mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-03 07:55:36 +00:00
Merge branch '7.0'
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Modal, ModalHeader, ModalBody, TabContent, TabPane, Nav, NavItem, NavLink } from 'reactstrap';
|
||||
import { gettext, canGenerateShareLink, canGenerateUploadLink } from '../../utils/constants';
|
||||
import { gettext, username, canGenerateShareLink, canGenerateUploadLink } from '../../utils/constants';
|
||||
import ShareToUser from './share-to-user';
|
||||
import ShareToGroup from './share-to-group';
|
||||
import GenerateShareLink from './generate-share-link';
|
||||
import GenerateUploadLink from './generate-upload-link';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import Loading from '../loading';
|
||||
import '../../css/share-link-dialog.css';
|
||||
|
||||
const propTypes = {
|
||||
@@ -24,10 +26,23 @@ class ShareDialog extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
activeTab: this.getInitialActiveTab()
|
||||
activeTab: this.getInitialActiveTab(),
|
||||
isRepoJudgemented: false,
|
||||
isRepoOwner: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
let repoID = this.props.repoID;
|
||||
seafileAPI.getRepoInfo(repoID).then(res => {
|
||||
let isRepoOwner = res.data.owner_email === username;
|
||||
this.setState({
|
||||
isRepoJudgemented: true,
|
||||
isRepoOwner: isRepoOwner,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getInitialActiveTab = () => {
|
||||
const {repoEncrypted, userPerm, enableDirPrivateShare} = this.props;
|
||||
const enableShareLink = !repoEncrypted && canGenerateShareLink;
|
||||
@@ -49,8 +64,12 @@ class ShareDialog extends React.Component {
|
||||
}
|
||||
|
||||
renderDirContent = () => {
|
||||
let activeTab = this.state.activeTab;
|
||||
|
||||
if (!this.state.isRepoJudgemented) {
|
||||
return <Loading />;
|
||||
}
|
||||
|
||||
let activeTab = this.state.activeTab;
|
||||
const {repoEncrypted, userPerm, enableDirPrivateShare} = this.props;
|
||||
const enableShareLink = !repoEncrypted && canGenerateShareLink;
|
||||
const enableUploadLink = !repoEncrypted && canGenerateUploadLink && userPerm == 'rw';
|
||||
@@ -112,10 +131,10 @@ class ShareDialog extends React.Component {
|
||||
{enableDirPrivateShare &&
|
||||
<Fragment>
|
||||
<TabPane tabId="shareToUser">
|
||||
<ShareToUser itemType={this.props.itemType} isGroupOwnedRepo={this.props.isGroupOwnedRepo} itemPath={this.props.itemPath} repoID={this.props.repoID} />
|
||||
<ShareToUser itemType={this.props.itemType} isGroupOwnedRepo={this.props.isGroupOwnedRepo} itemPath={this.props.itemPath} repoID={this.props.repoID} isRepoOwner={this.state.isRepoOwner}/>
|
||||
</TabPane>
|
||||
<TabPane tabId="shareToGroup">
|
||||
<ShareToGroup itemType={this.props.itemType} isGroupOwnedRepo={this.props.isGroupOwnedRepo} itemPath={this.props.itemPath} repoID={this.props.repoID} />
|
||||
<ShareToGroup itemType={this.props.itemType} isGroupOwnedRepo={this.props.isGroupOwnedRepo} itemPath={this.props.itemPath} repoID={this.props.repoID} isRepoOwner={this.state.isRepoOwner}/>
|
||||
</TabPane>
|
||||
</Fragment>
|
||||
}
|
||||
|
@@ -36,6 +36,7 @@ class GroupItem extends React.Component {
|
||||
|
||||
render() {
|
||||
let item = this.props.item;
|
||||
let currentPermission = item.is_admin ? 'admin' : item.permission;
|
||||
return (
|
||||
<tr onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>
|
||||
<td className='name'>{item.group_info.name}</td>
|
||||
@@ -43,7 +44,7 @@ class GroupItem extends React.Component {
|
||||
<SharePermissionEditor
|
||||
isTextMode={true}
|
||||
isEditIconShow={this.state.isOperationShow}
|
||||
currentPermission={item.permission}
|
||||
currentPermission={currentPermission}
|
||||
permissions={this.props.permissions}
|
||||
onPermissionChanged={this.onChangeUserPermission}
|
||||
/>
|
||||
@@ -87,7 +88,8 @@ const propTypes = {
|
||||
isGroupOwnedRepo: PropTypes.bool,
|
||||
itemPath: PropTypes.string.isRequired,
|
||||
itemType: PropTypes.string.isRequired,
|
||||
repoID: PropTypes.string.isRequired
|
||||
repoID: PropTypes.string.isRequired,
|
||||
isRepoOwner: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
const NoOptionsMessage = (props) => {
|
||||
@@ -108,9 +110,10 @@ class ShareToGroup extends React.Component {
|
||||
};
|
||||
this.options = [];
|
||||
this.permissions = []
|
||||
if (this.props.itemType === 'library') {
|
||||
this.permissions = ['rw', 'r', 'admin', 'cloud-edit', 'preview'];
|
||||
} else if (this.props.itemType === 'dir') {
|
||||
let { itemType, isRepoOwner } = props;
|
||||
if (itemType === 'library') {
|
||||
this.permissions = isRepoOwner ? ['rw', 'r', 'admin', 'cloud-edit', 'preview'] : ['rw', 'r', 'cloud-edit', 'preview'];
|
||||
} else if (itemType === 'dir') {
|
||||
this.permissions = ['rw', 'r', 'cloud-edit', 'preview'];
|
||||
}
|
||||
if (this.props.isGroupOwnedRepo || !isPro) {
|
||||
@@ -251,6 +254,7 @@ class ShareToGroup extends React.Component {
|
||||
if (groupID === sharedItemGroupID) {
|
||||
sharedItem.permission = permission;
|
||||
}
|
||||
sharedItem.is_admin = permission === 'admin' ? true : false;
|
||||
return sharedItem;
|
||||
});
|
||||
this.setState({sharedItems: sharedItems});
|
||||
|
@@ -88,7 +88,8 @@ const propTypes = {
|
||||
isGroupOwnedRepo: PropTypes.bool,
|
||||
itemPath: PropTypes.string.isRequired,
|
||||
itemType: PropTypes.string.isRequired,
|
||||
repoID: PropTypes.string.isRequired
|
||||
repoID: PropTypes.string.isRequired,
|
||||
isRepoOwner: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
class ShareToUser extends React.Component {
|
||||
@@ -103,8 +104,9 @@ class ShareToUser extends React.Component {
|
||||
};
|
||||
this.options = [];
|
||||
this.permissions = [];
|
||||
if (this.props.itemType === 'library') {
|
||||
this.permissions = ['rw', 'r', 'admin', 'cloud-edit', 'preview'];
|
||||
let { itemType, isRepoOwner } = props;
|
||||
if (itemType === 'library') {
|
||||
this.permissions = isRepoOwner ? ['rw', 'r', 'admin', 'cloud-edit', 'preview'] : ['rw', 'r', 'cloud-edit', 'preview'];
|
||||
} else if (this.props.itemType === 'dir') {
|
||||
this.permissions = ['rw', 'r', 'cloud-edit', 'preview'];
|
||||
}
|
||||
@@ -319,13 +321,13 @@ class ShareToUser extends React.Component {
|
||||
deleteShareItem={this.deleteShareItem}
|
||||
onChangeUserPermission={this.onChangeUserPermission}
|
||||
/>
|
||||
{ canInvitePeople &&
|
||||
<a href={siteRoot + 'invitations/'} className="invite-link-in-popup">
|
||||
<i className="sf2-icon-invite invite-link-icon-in-popup"></i>
|
||||
<span className="invite-link-icon-in-popup">{gettext('Invite People')}</span>
|
||||
</a>
|
||||
}
|
||||
</table>
|
||||
{canInvitePeople &&
|
||||
<a href={siteRoot + 'invitations/'} className="invite-link-in-popup">
|
||||
<i className="sf2-icon-invite invite-link-icon-in-popup"></i>
|
||||
<span className="invite-link-icon-in-popup">{gettext('Invite People')}</span>
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
</Fragment>
|
||||
);
|
||||
|
@@ -392,6 +392,10 @@ class DirentGridView extends React.Component{
|
||||
menuList: menuList,
|
||||
};
|
||||
|
||||
if (menuList.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
showMenu(showMenuConfig);
|
||||
}
|
||||
|
||||
@@ -408,11 +412,17 @@ class DirentGridView extends React.Component{
|
||||
let contextmenuList = [];
|
||||
if (isContextmenu) {
|
||||
let { SHARE, DOWNLOAD, DELETE } = TextTranslation;
|
||||
contextmenuList = this.props.showShareBtn ? [SHARE, DOWNLOAD, DELETE, 'Divider'] : [DOWNLOAD, DELETE, 'Divider'];
|
||||
contextmenuList = this.props.showShareBtn ? [SHARE] : [];
|
||||
|
||||
if (dirent.type === 'file') {
|
||||
contextmenuList = canGenerateShareLink ? [SHARE, DOWNLOAD, DELETE, 'Divider'] : [DOWNLOAD, DELETE, 'Divider'];
|
||||
if (dirent.permission === 'rw' || dirent.permission === 'r') {
|
||||
contextmenuList = [...contextmenuList, DOWNLOAD];
|
||||
}
|
||||
|
||||
if (dirent.permission === 'rw') {
|
||||
contextmenuList = [...contextmenuList, DELETE];
|
||||
}
|
||||
|
||||
contextmenuList = [...contextmenuList, 'Divider'];
|
||||
}
|
||||
|
||||
let { RENAME, MOVE, COPY, PERMISSION, OPEN_VIA_CLIENT, LOCK, UNLOCK, COMMENT, HISTORY, ACCESS_LOG } = TextTranslation;
|
||||
|
@@ -2,7 +2,7 @@ import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import MD5 from 'MD5';
|
||||
import { UncontrolledTooltip } from 'reactstrap';
|
||||
import { gettext, siteRoot, mediaUrl, username, canGenerateShareLink } from '../../utils/constants';
|
||||
import { gettext, siteRoot, mediaUrl, username } from '../../utils/constants';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import URLDecorator from '../../utils/url-decorator';
|
||||
@@ -411,7 +411,7 @@ class DirentListItem extends React.Component {
|
||||
dragStartItemData = JSON.parse(dragStartItemData);
|
||||
if (Array.isArray(dragStartItemData)) { //move items
|
||||
let direntPaths = dragStartItemData.map(draggedItem => {
|
||||
return draggedItem.nodeRootPath
|
||||
return draggedItem.nodeRootPath;
|
||||
});
|
||||
|
||||
let selectedPath = Utils.joinPath(this.props.path, this.props.dirent.name);
|
||||
@@ -462,7 +462,7 @@ class DirentListItem extends React.Component {
|
||||
if (currentRepoInfo.permission === 'cloud-edit' || currentRepoInfo.permission === 'preview') {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
{selectedDirentList.length > 1 ?
|
||||
@@ -470,17 +470,21 @@ class DirentListItem extends React.Component {
|
||||
{this.state.isOperationShow && !dirent.isSelected &&
|
||||
<div className="operations">
|
||||
<ul className="operation-group">
|
||||
<li className="operation-group-item">
|
||||
<i className="op-icon sf2-icon-download" title={gettext('Download')} onClick={this.onItemDownload}></i>
|
||||
</li>
|
||||
{showShareBtn &&
|
||||
<li className="operation-group-item">
|
||||
<i className="op-icon sf2-icon-share" title={gettext('Share')} onClick={this.onItemShare}></i>
|
||||
</li>
|
||||
}
|
||||
<li className="operation-group-item">
|
||||
<i className="op-icon sf2-icon-delete" title={gettext('Delete')} onClick={this.onItemDelete}></i>
|
||||
</li>
|
||||
{(dirent.permission === 'rw' || dirent.permission === 'r') && (
|
||||
<li className="operation-group-item">
|
||||
<i className="op-icon sf2-icon-download" title={gettext('Download')} onClick={this.onItemDownload}></i>
|
||||
</li>
|
||||
)}
|
||||
{showShareBtn && (
|
||||
<li className="operation-group-item">
|
||||
<i className="op-icon sf2-icon-share" title={gettext('Share')} onClick={this.onItemShare}></i>
|
||||
</li>
|
||||
)}
|
||||
{dirent.permission === 'rw' && (
|
||||
<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}
|
||||
@@ -500,17 +504,21 @@ class DirentListItem extends React.Component {
|
||||
{this.state.isOperationShow &&
|
||||
<div className="operations">
|
||||
<ul className="operation-group">
|
||||
<li className="operation-group-item">
|
||||
<i className="op-icon sf2-icon-download" title={gettext('Download')} onClick={this.onItemDownload}></i>
|
||||
</li>
|
||||
{showShareBtn &&
|
||||
<li className="operation-group-item">
|
||||
<i className="op-icon sf2-icon-share" title={gettext('Share')} onClick={this.onItemShare}></i>
|
||||
</li>
|
||||
}
|
||||
<li className="operation-group-item">
|
||||
<i className="op-icon sf2-icon-delete" title={gettext('Delete')} onClick={this.onItemDelete}></i>
|
||||
</li>
|
||||
{(dirent.permission === 'rw' || dirent.permission === 'r') && (
|
||||
<li className="operation-group-item">
|
||||
<i className="op-icon sf2-icon-download" title={gettext('Download')} onClick={this.onItemDownload}></i>
|
||||
</li>
|
||||
)}
|
||||
{showShareBtn && (
|
||||
<li className="operation-group-item">
|
||||
<i className="op-icon sf2-icon-share" title={gettext('Share')} onClick={this.onItemShare}></i>
|
||||
</li>
|
||||
)}
|
||||
{dirent.permission === 'rw' && (
|
||||
<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}
|
||||
|
@@ -320,6 +320,10 @@ class DirentListView extends React.Component {
|
||||
menuList: menuList,
|
||||
};
|
||||
|
||||
if (menuList.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
showMenu(showMenuConfig);
|
||||
}
|
||||
|
||||
@@ -467,21 +471,28 @@ class DirentListView extends React.Component {
|
||||
|
||||
let menuList = [];
|
||||
let contextmenuList = [];
|
||||
|
||||
if (isContextmenu) {
|
||||
let { SHARE, DOWNLOAD, DELETE } = TextTranslation;
|
||||
contextmenuList = this.props.showShareBtn ? [SHARE, DOWNLOAD, DELETE, 'Divider'] : [DOWNLOAD, DELETE, 'Divider'];
|
||||
contextmenuList = this.props.showShareBtn ? [SHARE] : [];
|
||||
|
||||
if (dirent.type === 'file') {
|
||||
contextmenuList = canGenerateShareLink ? [SHARE, DOWNLOAD, DELETE, 'Divider'] : [DOWNLOAD, DELETE, 'Divider'];
|
||||
if (dirent.permission === 'rw' || dirent.permission === 'r') {
|
||||
contextmenuList = [...contextmenuList, DOWNLOAD];
|
||||
}
|
||||
|
||||
if (dirent.permission === 'rw') {
|
||||
contextmenuList = [...contextmenuList, DELETE];
|
||||
}
|
||||
|
||||
contextmenuList = [...contextmenuList, 'Divider'];
|
||||
}
|
||||
|
||||
let { RENAME, MOVE, COPY, PERMISSION, OPEN_VIA_CLIENT, LOCK, UNLOCK, COMMENT, HISTORY, ACCESS_LOG, TAGS } = TextTranslation;
|
||||
if (type === 'dir' && permission === 'rw') {
|
||||
if (can_set_folder_perm) {
|
||||
menuList = [...contextmenuList, RENAME, MOVE, COPY, 'Divider', PERMISSION, 'Divider', OPEN_VIA_CLIENT];
|
||||
menuList = [...menuList, RENAME, MOVE, COPY, 'Divider', PERMISSION, 'Divider', OPEN_VIA_CLIENT];
|
||||
} else {
|
||||
menuList = [...contextmenuList, RENAME, MOVE, COPY, 'Divider', OPEN_VIA_CLIENT];
|
||||
menuList = [...menuList, RENAME, MOVE, COPY, 'Divider', OPEN_VIA_CLIENT];
|
||||
}
|
||||
return menuList;
|
||||
}
|
||||
|
@@ -218,7 +218,7 @@ class IndexContentViewer extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="mx-2 o-hidden">
|
||||
<div className="mx-4 o-hidden">
|
||||
<FolderItem node={this.treeRoot} bindClickEvent={this.bindClickEvent} currentPath={this.state.currentPath}/>
|
||||
</div>
|
||||
);
|
||||
|
@@ -127,21 +127,25 @@ class WikiMarkdownViewer extends React.Component {
|
||||
|
||||
changeInlineNode = (item) => {
|
||||
if (item.object == 'inline') {
|
||||
let url;
|
||||
let url, imagePath;
|
||||
|
||||
// change image url
|
||||
if (item.type == 'image' && isPublicWiki) {
|
||||
url = item.data.src;
|
||||
const re = new RegExp(serviceURL + '/lib/' + repoID +'/file.*raw=1');
|
||||
// different repo
|
||||
if (!re.test(url)) {
|
||||
if (re.test(url)) {
|
||||
// get image path
|
||||
let index = url.indexOf('/file');
|
||||
let index2 = url.indexOf('?');
|
||||
imagePath = url.substring(index + 5, index2);
|
||||
} else if (/^\.\.\/*/.test(url) || /^\.\/*/.test(url)) {
|
||||
const path = this.props.path;
|
||||
const originalPath = path.slice(0, path.lastIndexOf('/')) + '/' + url;
|
||||
imagePath = Utils.pathNormalize(originalPath);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
// get image path
|
||||
let index = url.indexOf('/file');
|
||||
let index2 = url.indexOf('?');
|
||||
const imagePath = url.substring(index + 5, index2);
|
||||
// replace url
|
||||
item.data.src = serviceURL + '/view-image-via-public-wiki/?slug=' + slug + '&path=' + imagePath;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user