mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-02 07:27:04 +00:00
conflict fixed
This commit is contained in:
10
frontend/src/components/common/logout.js
Normal file
10
frontend/src/components/common/logout.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import React from 'react';
|
||||
import { siteRoot, gettext } from '../../utils/constants';
|
||||
|
||||
export default function Logout() {
|
||||
return (
|
||||
<a className="logout-icon" href={`${siteRoot}accounts/logout/`} title={gettext('Log out')}>
|
||||
<i className="sf3-font sf3-font-logout" style={{fontSize: '24px'}}></i>
|
||||
</a>
|
||||
);
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Modal, ModalBody } from 'reactstrap';
|
||||
import { gettext, lang, mediaUrl, logoPath, logoWidth, logoHeight, siteTitle, seafileVersion } from '../../utils/constants';
|
||||
import { gettext, lang, mediaUrl, logoPath, logoWidth, logoHeight, siteTitle, seafileVersion, extraAboutDialogLinks } from '../../utils/constants';
|
||||
|
||||
const propTypes = {
|
||||
onCloseAboutDialog: PropTypes.func.isRequired,
|
||||
@@ -13,6 +13,16 @@ class AboutDialog extends React.Component {
|
||||
this.props.onCloseAboutDialog();
|
||||
}
|
||||
|
||||
renderExternalAboutLinks = () => {
|
||||
if (extraAboutDialogLinks && (typeof extraAboutDialogLinks) === 'object') {
|
||||
let keys = Object.keys(extraAboutDialogLinks);
|
||||
return keys.map((key, index) => {
|
||||
return <a key={index} className="d-block" href={extraAboutDialogLinks[key]}>{key}</a>;
|
||||
});
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
render() {
|
||||
let href = lang === lang == 'zh-cn' ? 'http://seafile.com/about/' : 'http://seafile.com/en/about/';
|
||||
|
||||
@@ -23,6 +33,7 @@ class AboutDialog extends React.Component {
|
||||
<div className="about-content">
|
||||
<p><img src={mediaUrl + logoPath} height={logoHeight} width={logoWidth} title={siteTitle} alt="logo" /></p>
|
||||
<p>{gettext('Server Version: ')}{seafileVersion}<br />© 2019 {gettext('Seafile')}</p>
|
||||
<p>{this.renderExternalAboutLinks()}</p>
|
||||
<p><a href={href} target="_blank">{gettext('About Us')}</a></p>
|
||||
</div>
|
||||
</ModalBody>
|
||||
|
@@ -23,7 +23,7 @@ class CopyMoveDirentProgressDialog extends React.Component {
|
||||
textAlign: 'left',
|
||||
};
|
||||
return (
|
||||
<Modal isOpen={true} toggle={this.props.toggleDialog}>
|
||||
<Modal isOpen={true}>
|
||||
<ModalHeader toggle={this.props.toggleDialog}>{title}</ModalHeader>
|
||||
<ModalBody style={{minHeight: '80px'}}>
|
||||
<div className="progress" style={{height: '40px'}}>
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Modal, ModalHeader, ModalBody, TabContent, TabPane, Nav, NavItem, NavLink } from 'reactstrap';
|
||||
import { gettext, username, canGenerateShareLink, canGenerateUploadLink, canInvitePeople } from '../../utils/constants';
|
||||
import { gettext, username, canGenerateShareLink, canGenerateUploadLink, canInvitePeople, extraShareDialogNote } from '../../utils/constants';
|
||||
import ShareToUser from './share-to-user';
|
||||
import ShareToGroup from './share-to-group';
|
||||
import ShareToInvitePeople from './share-to-invite-people';
|
||||
@@ -226,13 +226,28 @@ class ShareDialog extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
renderExternalShareMessage = () => {
|
||||
if (extraShareDialogNote && (typeof extraShareDialogNote) === 'object') {
|
||||
return (
|
||||
<div className="external-share-message mt-2">
|
||||
<h6>{extraShareDialogNote.title}</h6>
|
||||
<div style={{fontSize: '14px', color: '#666'}}>{extraShareDialogNote.content}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { itemType, itemName, repoEncrypted } = this.props;
|
||||
const enableShareLink = !repoEncrypted && canGenerateShareLink;
|
||||
return (
|
||||
<div>
|
||||
<Modal isOpen={true} style={{ maxWidth: '720px' }} className="share-dialog" toggle={this.props.toggleDialog}>
|
||||
<ModalHeader toggle={this.props.toggleDialog}>{gettext('Share')} <span className="op-target" title={itemName}>{itemName}</span></ModalHeader>
|
||||
<Modal isOpen={true} style={{maxWidth: '720px'}} className="share-dialog" toggle={this.props.toggleDialog}>
|
||||
<ModalHeader toggle={this.props.toggleDialog}>
|
||||
{gettext('Share')} <span className="op-target" title={itemName}>{itemName}</span>
|
||||
{this.renderExternalShareMessage()}
|
||||
</ModalHeader>
|
||||
<ModalBody className="share-dialog-content">
|
||||
{(itemType === 'library' || itemType === 'dir') && this.renderDirContent()}
|
||||
{(itemType === 'file' && enableShareLink) && this.renderFileContent()}
|
||||
|
@@ -279,8 +279,8 @@ class ShareToGroup extends React.Component {
|
||||
let sharedItemGroupID = sharedItem.group_info.id;
|
||||
if (groupID === sharedItemGroupID) {
|
||||
sharedItem.permission = permission;
|
||||
sharedItem.is_admin = permission === 'admin' ? true : false;
|
||||
}
|
||||
sharedItem.is_admin = permission === 'admin' ? true : false;
|
||||
return sharedItem;
|
||||
});
|
||||
this.setState({sharedItems: sharedItems});
|
||||
|
@@ -263,8 +263,8 @@ class ShareToUser extends React.Component {
|
||||
let sharedItemUsername = sharedItem.user_info.name;
|
||||
if (username === sharedItemUsername) {
|
||||
sharedItem.permission = permission;
|
||||
sharedItem.is_admin = permission === 'admin' ? true : false;
|
||||
}
|
||||
sharedItem.is_admin = permission === 'admin' ? true : false;
|
||||
return sharedItem;
|
||||
});
|
||||
this.setState({sharedItems: sharedItems});
|
||||
|
@@ -94,29 +94,52 @@ class Search extends Component {
|
||||
|
||||
sendRequest(queryData, cancelToken) {
|
||||
var _this = this;
|
||||
let isPublic = this.props.isPublic;
|
||||
|
||||
seafileAPI.searchFiles(queryData, cancelToken).then(res => {
|
||||
if (!res.data.total) {
|
||||
if (isPublic) {
|
||||
seafileAPI.searchFilesInPublishedRepo(queryData.search_repo, queryData.q).then(res => {
|
||||
if (!res.data.total) {
|
||||
_this.setState({
|
||||
resultItems: [],
|
||||
isResultGetted: true
|
||||
});
|
||||
_this.source = null;
|
||||
return;
|
||||
}
|
||||
|
||||
let items = _this.formatResultItems(res.data.results);
|
||||
_this.setState({
|
||||
resultItems: [],
|
||||
resultItems: items,
|
||||
isResultGetted: true
|
||||
});
|
||||
_this.source = null;
|
||||
return;
|
||||
}
|
||||
|
||||
let items = _this.formatResultItems(res.data.results);
|
||||
_this.setState({
|
||||
total: res.data.total,
|
||||
resultItems: items,
|
||||
isResultGetted: true
|
||||
}).catch(error => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
_this.source = null;
|
||||
}).catch(res => {
|
||||
/* eslint-disable */
|
||||
} else {
|
||||
editorUtilities.searchFiles(queryData,cancelToken).then(res => {
|
||||
if (!res.data.total) {
|
||||
_this.setState({
|
||||
resultItems: [],
|
||||
isResultGetted: true
|
||||
});
|
||||
_this.source = null;
|
||||
return;
|
||||
}
|
||||
|
||||
let items = _this.formatResultItems(res.data.results);
|
||||
_this.setState({
|
||||
resultItems: items,
|
||||
isResultGetted: true
|
||||
});
|
||||
_this.source = null;
|
||||
}).catch(res => {
|
||||
/* eslint-disable */
|
||||
console.log(res);
|
||||
/* eslint-enable */
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
cancelRequest() {
|
||||
|
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { gettext } from '../../utils/constants';
|
||||
|
||||
const { err, trafficOverLimit, zipped, filePath } = window.shared.pageOptions;
|
||||
const { err, trafficOverLimit, zipped, filePath, canDownload } = window.shared.pageOptions;
|
||||
|
||||
const propTypes = {
|
||||
errorMsg: PropTypes.string
|
||||
@@ -16,11 +16,14 @@ class SharedFileViewTip extends React.Component {
|
||||
} else {
|
||||
errorMsg = <p className="error">{err || this.props.errorMsg}</p>;
|
||||
}
|
||||
|
||||
let isShowDownloadBtn = canDownload && !trafficOverLimit;
|
||||
|
||||
return (
|
||||
<div className="shared-file-view-body">
|
||||
<div className="file-view-tip">
|
||||
<div className={`file-view-tip ${!isShowDownloadBtn ? 'pt-7' : ''}`}>
|
||||
{errorMsg}
|
||||
{!trafficOverLimit &&
|
||||
{isShowDownloadBtn &&
|
||||
<a href={`?${zipped ? 'p=' + encodeURIComponent(filePath) + '&' : ''}dl=1`} className="btn btn-secondary">{gettext('Download')}</a>
|
||||
}
|
||||
</div>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { gettext, siteRoot } from '../utils/constants';
|
||||
import React, { Fragment } from 'react';
|
||||
import { gettext, siteRoot, sideNavFooterCustomHtml, extraAppBottomLinks } from '../utils/constants';
|
||||
import ModalPortal from './modal-portal';
|
||||
import AboutDialog from './dialog/about-dialog';
|
||||
|
||||
@@ -16,21 +16,38 @@ class SideNavFooter extends React.Component {
|
||||
this.setState({isAboutDialogShow: !this.state.isAboutDialogShow});
|
||||
}
|
||||
|
||||
renderExternalAppLinks = () => {
|
||||
if (extraAppBottomLinks && (typeof extraAppBottomLinks) === 'object') {
|
||||
let keys = Object.keys(extraAppBottomLinks);
|
||||
return keys.map((key, index) => {
|
||||
return <a key={index} className="item" href={extraAppBottomLinks[key]}>{key}</a>;
|
||||
});
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
if (sideNavFooterCustomHtml) {
|
||||
return (<div className='side-nav-footer' dangerouslySetInnerHTML={{__html: sideNavFooterCustomHtml}}></div>);
|
||||
}
|
||||
return (
|
||||
<div className="side-nav-footer">
|
||||
<a href={siteRoot + 'help/'} target="_blank" rel="noopener noreferrer" className="item">{gettext('Help')}</a>
|
||||
<a className="item cursor-pointer" onClick={this.onAboutDialogToggle}>{gettext('About')}</a>
|
||||
<a href={siteRoot + 'download_client_program/'} className="item last-item">
|
||||
<span aria-hidden="true" className="sf2-icon-monitor vam"></span>{' '}
|
||||
<span className="vam">{gettext('Clients')}</span>
|
||||
</a>
|
||||
{this.state.isAboutDialogShow &&
|
||||
<Fragment>
|
||||
<div className="side-nav-footer flex-wrap">
|
||||
<a href={siteRoot + 'help/'} target="_blank" rel="noopener noreferrer" className="item">{gettext('Help')}</a>
|
||||
<a className="item cursor-pointer" onClick={this.onAboutDialogToggle}>{gettext('About')}</a>
|
||||
{this.renderExternalAppLinks()}
|
||||
<a href={siteRoot + 'download_client_program/'} className={`item ${extraAppBottomLinks ? '' : 'last-item'}`}>
|
||||
<span aria-hidden="true" className="sf2-icon-monitor vam"></span>{' '}
|
||||
<span className="vam">{gettext('Clients')}</span>
|
||||
</a>
|
||||
</div>
|
||||
{this.state.isAboutDialogShow && (
|
||||
<ModalPortal>
|
||||
<AboutDialog onCloseAboutDialog={this.onAboutDialogToggle} />
|
||||
</ModalPortal>
|
||||
}
|
||||
</div>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -1,9 +1,10 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { isPro, gettext } from '../../utils/constants';
|
||||
import { isPro, gettext, showLogoutIcon } from '../../utils/constants';
|
||||
import Search from '../search/search';
|
||||
import Notification from '../common/notification';
|
||||
import Account from '../common/account';
|
||||
import Logout from '../common/logout';
|
||||
|
||||
const propTypes = {
|
||||
repoID: PropTypes.string,
|
||||
@@ -25,6 +26,7 @@ class CommonToolbar extends React.Component {
|
||||
)}
|
||||
<Notification />
|
||||
<Account />
|
||||
{showLogoutIcon && (<Logout />)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@@ -83,6 +83,17 @@
|
||||
.common-toolbar > div{
|
||||
margin-left: .5rem;
|
||||
}
|
||||
|
||||
.common-toolbar .logout-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin-left: 8px;
|
||||
text-decoration: none;
|
||||
color: #ccc;
|
||||
}
|
||||
/* end common-toolbar */
|
||||
|
||||
/* begin path toolbar */
|
||||
|
@@ -78,6 +78,29 @@ class EditorUtilities {
|
||||
return url;
|
||||
}
|
||||
|
||||
uploadImage = (imageFile) => {
|
||||
return (
|
||||
seafileAPI.getFileServerUploadLink(repoID, dirPath).then((res) => {
|
||||
let uploadLinkComponent = res.data;
|
||||
const uploadLink = uploadLinkComponent + '?ret-json=1';
|
||||
const name = getImageFileNameWithTimestamp();
|
||||
const blob = imageFile.slice(0, -1, 'image/png');
|
||||
const newFile = new File([blob], name, {type: 'image/png'});
|
||||
const formData = new FormData();
|
||||
formData.append('parent_dir', '/');
|
||||
formData.append('relative_path', 'images/auto-upload');
|
||||
formData.append('file', newFile);
|
||||
return {uploadLink, formData};
|
||||
}).then(({ uploadLink, formData}) => {
|
||||
return seafileAPI.uploadImage(uploadLink, formData);
|
||||
}).then ((res) => {
|
||||
let resArr = res.data[0];
|
||||
let filename = resArr.name;
|
||||
return this._getImageURL(filename);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
uploadLocalImage = (imageFile) => {
|
||||
return (
|
||||
seafileAPI.getFileServerUploadLink(repoID, dirPath).then((res) => {
|
||||
|
@@ -77,6 +77,7 @@ class LibContentView extends React.Component {
|
||||
isSessionExpired: false,
|
||||
isCopyMoveProgressDialogShow: false,
|
||||
asyncCopyMoveTaskId: '',
|
||||
asyncOperationType: 'move',
|
||||
asyncOperationProgress: 0,
|
||||
asyncOperatedFilesLength: 0,
|
||||
};
|
||||
@@ -632,18 +633,18 @@ class LibContentView extends React.Component {
|
||||
// toolbar operations
|
||||
onMoveItems = (destRepo, destDirentPath) => {
|
||||
let repoID = this.props.repoID;
|
||||
let direntPaths = this.getSelectedDirentPaths();
|
||||
let dirNames = this.getSelectedDirentNames();
|
||||
|
||||
let selectedDirentList = this.state.selectedDirentList;
|
||||
if (repoID !== destRepo.repo_id) {
|
||||
this.setState({
|
||||
asyncOperatedFilesLength: dirNames.length,
|
||||
this.setState(() => ({
|
||||
asyncOperatedFilesLength: selectedDirentList.length,
|
||||
asyncOperationProgress: 0,
|
||||
asyncOperationType: 'move',
|
||||
isCopyMoveProgressDialogShow: true
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
let dirNames = this.getSelectedDirentNames();
|
||||
let direntPaths = this.getSelectedDirentPaths();
|
||||
seafileAPI.moveDir(repoID, destRepo.repo_id, destDirentPath, this.state.path, dirNames).then(res => {
|
||||
if (repoID !== destRepo.repo_id) {
|
||||
this.setState({
|
||||
@@ -682,17 +683,18 @@ class LibContentView extends React.Component {
|
||||
|
||||
onCopyItems = (destRepo, destDirentPath) => {
|
||||
let repoID = this.props.repoID;
|
||||
let dirNames = this.getSelectedDirentNames();
|
||||
let selectedDirentList = this.state.selectedDirentList;
|
||||
|
||||
if (repoID !== destRepo.repo_id) {
|
||||
this.setState({
|
||||
asyncOperatedFilesLength: dirNames.length,
|
||||
asyncOperatedFilesLength: selectedDirentList.length,
|
||||
asyncOperationProgress: 0,
|
||||
asyncOperationType: 'copy',
|
||||
isCopyMoveProgressDialogShow: true
|
||||
});
|
||||
}
|
||||
|
||||
let dirNames = this.getSelectedDirentNames();
|
||||
seafileAPI.copyDir(repoID, destRepo.repo_id, destDirentPath, this.state.path, dirNames).then(res => {
|
||||
if (repoID !== destRepo.repo_id) {
|
||||
this.setState({
|
||||
@@ -1715,7 +1717,7 @@ class LibContentView extends React.Component {
|
||||
}
|
||||
|
||||
let enableDirPrivateShare = false;
|
||||
let { currentRepoInfo, userPerm } = this.state;
|
||||
let { currentRepoInfo, userPerm, isCopyMoveProgressDialogShow } = this.state;
|
||||
let showShareBtn = Utils.isHasPermissionToShare(currentRepoInfo, userPerm);
|
||||
let isRepoOwner = currentRepoInfo.owner_email === username;
|
||||
let isVirtual = currentRepoInfo.is_virtual;
|
||||
@@ -1860,7 +1862,7 @@ class LibContentView extends React.Component {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{this.state.isCopyMoveProgressDialogShow && (
|
||||
{isCopyMoveProgressDialogShow && (
|
||||
<CopyMoveDirentProgressDialog
|
||||
type={this.state.asyncOperationType}
|
||||
asyncOperatedFilesLength={this.state.asyncOperatedFilesLength}
|
||||
|
@@ -1,12 +1,11 @@
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { gettext, repoID, slug, siteRoot, username } from '../../utils/constants';
|
||||
import CommonToolbar from '../../components/toolbar/common-toolbar';
|
||||
import { gettext, repoID, slug, siteRoot, username, isPro } from '../../utils/constants';
|
||||
import WikiMarkdownViewer from '../../components/wiki-markdown-viewer';
|
||||
import WikiDirListView from '../../components/wiki-dir-list-view/wiki-dir-list-view';
|
||||
import Loading from '../../components/loading';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import Search from '../../components/search/wiki-search';
|
||||
import Search from '../../components/search/search';
|
||||
import Notification from '../../components/common/notification';
|
||||
import Account from '../../components/common/account';
|
||||
|
||||
@@ -78,6 +77,8 @@ class MainPanel extends Component {
|
||||
|
||||
|
||||
render() {
|
||||
let { onSearchedClick, permission } = this.props;
|
||||
let searchPlaceholder = gettext('Search files in this library');
|
||||
const errMessage = (<div className="message err-tip">{gettext('Folder does not exist.')}</div>);
|
||||
|
||||
const isViewingFile = this.props.pathExist && !this.props.isDataLoading && this.props.isViewFile;
|
||||
@@ -90,11 +91,9 @@ class MainPanel extends Component {
|
||||
<span className="sf2-icon-menu hidden-md-up d-md-none side-nav-toggle" title="Side Nav Menu" onClick={this.onMenuClick}></span>
|
||||
</div>
|
||||
<div className="common-toolbar">
|
||||
<Search
|
||||
repoID={repoID}
|
||||
onSearchedClick={this.props.onSearchedClick}
|
||||
placeholder={gettext('Search')}
|
||||
/>
|
||||
{isPro && (
|
||||
<Search isPublic={true} repoID={repoID} onSearchedClick={onSearchedClick} placeholder={searchPlaceholder}/>
|
||||
)}
|
||||
</div>
|
||||
</Fragment>
|
||||
}
|
||||
@@ -109,11 +108,9 @@ class MainPanel extends Component {
|
||||
)}
|
||||
</div>
|
||||
<div className="common-toolbar">
|
||||
<Search
|
||||
repoID={repoID}
|
||||
onSearchedClick={this.props.onSearchedClick}
|
||||
placeholder={gettext('Search')}
|
||||
/>
|
||||
{isPro && (
|
||||
<Search isPublic={true} repoID={repoID} onSearchedClick={onSearchedClick} placeholder={searchPlaceholder}/>
|
||||
)}
|
||||
<Notification />
|
||||
<Account />
|
||||
</div>
|
||||
|
@@ -50,9 +50,10 @@ class FileContent extends React.Component {
|
||||
return;
|
||||
}
|
||||
// get image path
|
||||
let index = imageUrl.indexOf('/file');
|
||||
let index2 = imageUrl.indexOf('?');
|
||||
const imagePath = imageUrl.substring(index + 5, index2);
|
||||
let imagePath = imageUrl.substring(serviceURL.length);
|
||||
let index = imagePath.indexOf('/file');
|
||||
let index2 = imagePath.indexOf('?');
|
||||
imagePath = imagePath.substring(index + 5, index2);
|
||||
// change image url
|
||||
innerNode.data.src = serviceURL + '/view-image-via-share-link/?token=' + sharedToken + '&path=' + imagePath;
|
||||
}
|
||||
|
@@ -46,6 +46,7 @@ export const enableRepoSnapshotLabel = window.app.pageOptions.enableRepoSnapshot
|
||||
export const shareLinkPasswordMinLength = window.app.pageOptions.shareLinkPasswordMinLength;
|
||||
export const shareLinkExpireDaysMin = window.app.pageOptions.shareLinkExpireDaysMin;
|
||||
export const shareLinkExpireDaysMax = window.app.pageOptions.shareLinkExpireDaysMax;
|
||||
export const sideNavFooterCustomHtml = window.app.pageOptions.sideNavFooterCustomHtml;
|
||||
export const shareLinkExpireDaysDefault = window.app.pageOptions.shareLinkExpireDaysDefault;
|
||||
export const maxFileName = window.app.pageOptions.maxFileName;
|
||||
export const canPublishRepo = window.app.pageOptions.canPublishRepo;
|
||||
@@ -66,6 +67,10 @@ export const curNoteID = window.app.pageOptions.curNoteID;
|
||||
|
||||
// dtable
|
||||
export const workspaceID = window.app.pageOptions.workspaceID;
|
||||
export const showLogoutIcon = window.app.pageOptions.showLogoutIcon;
|
||||
export const extraShareDialogNote = window.app.pageOptions.extraShareDialogNote;
|
||||
export const extraAppBottomLinks = window.app.pageOptions.extraAppBottomLinks;
|
||||
export const extraAboutDialogLinks = window.app.pageOptions.extraAboutDialogLinks;
|
||||
|
||||
// wiki
|
||||
export const slug = window.wiki ? window.wiki.config.slug : '';
|
||||
|
@@ -1,10 +1,10 @@
|
||||
@font-face {font-family: "sf3-font";
|
||||
src: url('iconfont.eot?t=1584611062765'); /* IE9 */
|
||||
src: url('iconfont.eot?t=1584611062765#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
||||
url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'),
|
||||
url('iconfont.woff?t=1584611062765') format('woff'),
|
||||
url('iconfont.ttf?t=1584611062765') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
|
||||
url('iconfont.svg?t=1584611062765#sf3-font') format('svg'); /* iOS 4.1- */
|
||||
src: url('iconfont.eot?t=1585125551666'); /* IE9 */
|
||||
src: url('iconfont.eot?t=1585125551666#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
||||
url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'),
|
||||
url('iconfont.woff?t=1585125551666') format('woff'),
|
||||
url('iconfont.ttf?t=1585125551666') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
|
||||
url('iconfont.svg?t=1585125551666#sf3-font') format('svg'); /* iOS 4.1- */
|
||||
}
|
||||
|
||||
.sf3-font {
|
||||
@@ -15,6 +15,14 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.sf3-font-logout:before {
|
||||
content: "\e6bb";
|
||||
}
|
||||
|
||||
.sf3-font-sort-up-down:before {
|
||||
content: "\e6ba";
|
||||
}
|
||||
|
||||
.sf3-font-dingtalk:before {
|
||||
content: "\e6b8";
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
@@ -20,6 +20,12 @@ Created by iconfont
|
||||
/>
|
||||
<missing-glyph />
|
||||
|
||||
<glyph glyph-name="logout" unicode="" d="M572.8 249.6H310.4c-12.8 0-22.4 6.4-22.4 16v233.6c0 12.8 6.4 22.4 22.4 22.4H576V729.6c0 9.6 3.2 16 12.8 19.2 9.6 3.2 16 3.2 22.4-6.4l12.8-12.8L768 585.6l185.6-185.6c9.6-9.6 9.6-22.4 0-32l-265.6-265.6-76.8-76.8c-6.4-6.4-12.8-9.6-22.4-6.4-9.6 3.2-12.8 9.6-12.8 19.2v211.2h-3.2z m-160 496v-76.8H214.4c-41.6 0-73.6-28.8-73.6-70.4v-425.6c0-38.4 28.8-64 54.4-70.4h217.6v-76.8H204.8c-67.2 0-124.8 51.2-137.6 118.4 0 6.4-3.2 16-3.2 25.6V601.6C67.2 662.4 96 704 147.2 732.8c19.2 9.6 38.4 12.8 60.8 12.8h204.8z" horiz-adv-x="1024" />
|
||||
|
||||
|
||||
<glyph glyph-name="sort-up-down" unicode="" d="M729.6 499.2l-195.2 227.2c-12.8 12.8-35.2 12.8-48 0l-192-227.2c-16-19.2 0-51.2 25.6-51.2h377.6c32 0 48 32 32 51.2zM294.4 268.79999999999995l188.8-227.2c12.8-12.8 35.2-12.8 48 0l188.8 227.2c19.2 19.2 6.4 57.6-25.6 57.6H320c-25.6 0-41.6-32-25.6-57.6z" horiz-adv-x="1024" />
|
||||
|
||||
|
||||
<glyph glyph-name="dingtalk" unicode="" d="M512-96C249.6-96 32 121.6 32 384S249.6 864 512 864s480-217.6 480-480-217.6-480-480-480z m0 896C281.6 800 96 614.4 96 384s185.6-416 416-416 416 185.6 416 416S742.4 800 512 800z m217.6-380.8c-22.4-44.8-70.4-134.4-70.4-134.4l-19.2-25.6h73.6l-144-198.4 32 134.4H544l22.4 89.6c-22.4-6.4-38.4-12.8-60.8-19.2 0 0-28.8-32-89.6 22.4 0 0-38.4 35.2-19.2 44.8 9.6 3.2 41.6 16 70.4 22.4 38.4 6.4 70.4 16 70.4 16s-121.6-3.2-150.4 3.2-67.2 48-73.6 92.8c0 0-12.8 25.6 25.6 12.8s198.4-35.2 198.4-35.2-208 67.2-217.6 83.2-41.6 86.4-38.4 128c0 0 0 12.8 12.8 9.6 0 0 153.6-70.4 259.2-115.2 105.6-38.4 195.2-60.8 182.4-112-3.2-6.4-6.4-12.8-6.4-19.2z" horiz-adv-x="1024" />
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 9.0 KiB |
109
seahub/api2/endpoints/repo_commit.py
Normal file
109
seahub/api2/endpoints/repo_commit.py
Normal file
@@ -0,0 +1,109 @@
|
||||
# Copyright (c) 2012-2019 Seafile Ltd.
|
||||
# encoding: utf-8
|
||||
|
||||
import logging
|
||||
|
||||
from rest_framework.authentication import SessionAuthentication
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework import status
|
||||
|
||||
from seaserv import seafile_api
|
||||
|
||||
from seahub.api2.throttling import UserRateThrottle
|
||||
from seahub.api2.authentication import TokenAuthentication
|
||||
from seahub.api2.utils import api_error
|
||||
from seahub.views import check_folder_permission
|
||||
from seahub.utils.timeutils import timestamp_to_isoformat_timestr
|
||||
from seahub.base.templatetags.seahub_tags import email2nickname, \
|
||||
email2contact_email
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class RepoCommitView(APIView):
|
||||
|
||||
authentication_classes = (TokenAuthentication, SessionAuthentication)
|
||||
permission_classes = (IsAuthenticated,)
|
||||
throttle_classes = (UserRateThrottle,)
|
||||
|
||||
def get(self, request, repo_id, commit_id, format=None):
|
||||
""" List commit info
|
||||
"""
|
||||
|
||||
# resource check
|
||||
repo = seafile_api.get_repo(repo_id)
|
||||
if not repo:
|
||||
error_msg = 'Library %s not found.' % repo_id
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
commit = seafile_api.get_commit(repo.id, repo.version, commit_id)
|
||||
if not commit:
|
||||
error_msg = 'Commit %s not found.' % commit_id
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
# permission check
|
||||
if not check_folder_permission(request, repo_id, '/'):
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
# commit __dict__
|
||||
#
|
||||
# {'_dict': {u'client_version': u'7.0.2',
|
||||
# u'conflict': False,
|
||||
# u'creator': u'30947ef13cd56439c72703ee74dcfa2a4d940cdb',
|
||||
# u'creator_name': u'lian@lian.com',
|
||||
# u'ctime': 1583893023,
|
||||
# u'desc': u'Added or modified "1.md" and 2 more files.\nDeleted "default.jpeg".\nRenamed "123.umind" and 1 more files.\nAdded "789" and 1 more directories.\nRemoved directory "456".\n',
|
||||
# u'device_name': u'lian mac pro work',
|
||||
# u'id': u'28c15cca4a8dbd5135fbe3ae75c3df7f5f355484',
|
||||
# u'new_merge': False,
|
||||
# u'next_start_commit': None,
|
||||
# u'parent_id': u'a12ece3a2ec69220bfa5f229682867faaf7448f7',
|
||||
# u'repo_id': u'8756ca9d-e3ed-44da-b43e-1bfd165b2377',
|
||||
# u'rev_file_id': None,
|
||||
# u'rev_file_size': 0,
|
||||
# u'rev_renamed_old_path': None,
|
||||
# u'root_id': u'0b7f91ad5137cf1d1e5be138ecd455ce76d2ee58',
|
||||
# u'second_parent_id': None,
|
||||
# u'version': 1},
|
||||
|
||||
# commit diff __dict__
|
||||
#
|
||||
# {'_dict': {u'status': None, u'new_name': u'xyz', u'name': u'abc'}, 'props': <pysearpc.client._SearpcObj object at 0x7ff4f81b2090>}
|
||||
# {'_dict': {u'status': u'mov', u'new_name': u'123.jpg', u'name': u'd0efd88ejw1f6vqsjmjh9j20c846i4i6.jpg'}, 'props': <pysearpc.client._SearpcObj object at 0x7fbc5478c090>}
|
||||
# {'_dict': {u'status': u'mod', u'new_name': None, u'name': u'123/1.md'}, 'props': <pysearpc.client._SearpcObj object at 0x7fbc5478c290>}
|
||||
# {'_dict': {u'status': u'deldir', u'new_name': None, u'name': u'123/456'}, 'props': <pysearpc.client._SearpcObj object at 0x7fbc5478c2d0>}
|
||||
# {'_dict': {u'status': u'newdir', u'new_name': None, u'name': u'123/789'}, 'props': <pysearpc.client._SearpcObj object at 0x7fbc5478c310>}
|
||||
# {'_dict': {u'status': u'del', u'new_name': None, u'name': u'default.jpeg'}, 'props': <pysearpc.client._SearpcObj object at 0x7fbc5478c390>}
|
||||
# {'_dict': {u'status': u'add', u'new_name': None, u'name': u'departments copy.md'}, 'props': <pysearpc.client._SearpcObj object at 0x7fbc5478c3d0>}
|
||||
|
||||
result = {}
|
||||
result['commit_info'] = {
|
||||
'creator_email': commit.creator_name,
|
||||
'creator_name': email2nickname(commit.creator_name),
|
||||
'creator_contact_email': email2contact_email(commit.creator_name),
|
||||
'time': timestamp_to_isoformat_timestr(commit.ctime),
|
||||
'description': commit.desc,
|
||||
'device_name': commit.device_name
|
||||
}
|
||||
result['commit_diffs'] = []
|
||||
|
||||
diffs = seafile_api.diff_commits(repo_id, '', commit_id)
|
||||
diff_status_dict = {
|
||||
"add": 'new',
|
||||
"del": 'removed',
|
||||
"mov": 'renamed',
|
||||
"mod": 'modified',
|
||||
"newdir": 'newdir',
|
||||
"deldir": 'deldir',
|
||||
}
|
||||
for diff in diffs:
|
||||
commit_diff = {}
|
||||
commit_diff['op_type'] = diff_status_dict.get(diff.status, '')
|
||||
commit_diff['path'] = '/' + diff.name if diff.name else ''
|
||||
commit_diff['new_path'] = '/' + diff.new_name if diff.new_name else ''
|
||||
result['commit_diffs'].append(commit_diff)
|
||||
|
||||
return Response(result)
|
@@ -46,6 +46,11 @@ except ImportError:
|
||||
ENABLE_FILE_SCAN = False
|
||||
from seahub.work_weixin.settings import ENABLE_WORK_WEIXIN
|
||||
|
||||
try:
|
||||
from seahub.settings import SIDE_NAV_FOOTER_CUSTOM_HTML
|
||||
except ImportError:
|
||||
SIDE_NAV_FOOTER_CUSTOM_HTML = ''
|
||||
|
||||
|
||||
def base(request):
|
||||
"""
|
||||
@@ -136,6 +141,7 @@ def base(request):
|
||||
'avatar_url': avatar_url if avatar_url else '',
|
||||
'privacy_policy_link': PRIVACY_POLICY_LINK,
|
||||
'terms_of_service_link': TERMS_OF_SERVICE_LINK,
|
||||
'side_nav_footer_custom_html': SIDE_NAV_FOOTER_CUSTOM_HTML,
|
||||
}
|
||||
|
||||
if request.user.is_staff:
|
||||
|
@@ -728,6 +728,39 @@ ENABLE_WIKI = True
|
||||
# Enable 'repo snapshot label' feature
|
||||
ENABLE_REPO_SNAPSHOT_LABEL = False
|
||||
|
||||
# Repo wiki mode
|
||||
ENABLE_REPO_WIKI_MODE = True
|
||||
|
||||
############################
|
||||
# HU berlin external#
|
||||
############################
|
||||
|
||||
# EXTRA_SHARE_DIALOG_NOTE = {
|
||||
# 'title': 'Attention! Read before shareing files:',
|
||||
# 'content': 'Do not share personal or confidential official data with **.'
|
||||
# }
|
||||
EXTRA_SHARE_DIALOG_NOTE = None
|
||||
|
||||
# EXTRA_APP_BOTTOM_LINKS = {
|
||||
# 'seafile': 'http://dev.seahub.com/seahub',
|
||||
# 'dtable-web': 'http://dev.seahub.com/dtable-web'
|
||||
# }
|
||||
EXTRA_APP_BOTTOM_LINKS = None
|
||||
|
||||
# EXTRA_ABOUT_DIALOG_LINKS = {
|
||||
# 'seafile': 'http://dev.seahub.com/seahub',
|
||||
# 'dtable-web': 'http://dev.seahub.com/dtable-web'
|
||||
# }
|
||||
EXTRA_ABOUT_DIALOG_LINKS = None
|
||||
|
||||
############################
|
||||
# Settings for SeafileDocs #
|
||||
############################
|
||||
if os.environ.get('SEAFILE_DOCS', None):
|
||||
LOGO_PATH = 'img/seafile-docs-logo.png'
|
||||
LOGO_WIDTH = ''
|
||||
ENABLE_WIKI = True
|
||||
|
||||
d = os.path.dirname
|
||||
EVENTS_CONFIG_FILE = os.environ.get(
|
||||
'EVENTS_CONFIG_FILE',
|
||||
|
@@ -86,6 +86,7 @@
|
||||
shareLinkExpireDaysDefault: {% if share_link_expire_days_default %} {{ share_link_expire_days_default }} {% else %} 0 {% endif %},
|
||||
shareLinkExpireDaysMin: "{{ share_link_expire_days_min }}",
|
||||
shareLinkExpireDaysMax: "{{ share_link_expire_days_max }}",
|
||||
sideNavFooterCustomHtml: "{{ side_nav_footer_custom_html|safe|escapejs }}",
|
||||
maxFileName: "{{ max_file_name }}",
|
||||
canPublishRepo: {% if user.permissions.can_publish_repo %} true {% else %} false {% endif %},
|
||||
enableEncryptedLibrary: {% if enable_encrypted_library %} true {% else %} false {% endif %},
|
||||
@@ -106,6 +107,10 @@
|
||||
curNoteMsg: '{{ request.cur_note.message|urlize|escapejs }}',
|
||||
curNoteID: '{{ request.cur_note.id }}',
|
||||
{% endif %}
|
||||
showLogoutIcon: {% if show_logout_icon %} true {% else %} false {% endif %},
|
||||
extraShareDialogNote: {% if extra_share_dialog_note %} {{ extra_share_dialog_note|safe }} {% else %} null {% endif %},
|
||||
extraAppBottomLinks: {% if extra_app_bottom_links %} {{ extra_app_bottom_links|safe }} {% else %} null {% endif %},
|
||||
extraAboutDialogLinks: {% if extra_about_dialog_links %} {{ extra_about_dialog_links|safe }} {% else %} null {% endif %}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
@@ -55,6 +55,7 @@ from seahub.api2.endpoints.dir import DirView, DirDetailView
|
||||
from seahub.api2.endpoints.file_tag import FileTagView
|
||||
from seahub.api2.endpoints.file_tag import FileTagsView
|
||||
from seahub.api2.endpoints.repo_trash import RepoTrash
|
||||
from seahub.api2.endpoints.repo_commit import RepoCommitView
|
||||
from seahub.api2.endpoints.repo_commit_dir import RepoCommitDirView
|
||||
from seahub.api2.endpoints.repo_commit_revert import RepoCommitRevertView
|
||||
from seahub.api2.endpoints.deleted_repos import DeletedRepos
|
||||
@@ -344,6 +345,7 @@ urlpatterns = [
|
||||
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/file/history/$', FileHistoryView.as_view(), name='api-v2.1-file-history-view'),
|
||||
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/file/new_history/$', NewFileHistoryView.as_view(), name='api-v2.1-new-file-history-view'),
|
||||
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/dir/$', DirView.as_view(), name='api-v2.1-dir-view'),
|
||||
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/commits/(?P<commit_id>[0-9a-f]{40})/$', RepoCommitView.as_view(), name='api-v2.1-repo-commit'),
|
||||
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/commits/(?P<commit_id>[0-9a-f]{40})/dir/$', RepoCommitDirView.as_view(), name='api-v2.1-repo-commit-dir'),
|
||||
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/commits/(?P<commit_id>[0-9a-f]{40})/revert/$', RepoCommitRevertView.as_view(), name='api-v2.1-repo-commit-revert'),
|
||||
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/dir/detail/$', DirDetailView.as_view(), name='api-v2.1-dir-detail-view'),
|
||||
|
@@ -55,6 +55,7 @@ from seahub.settings import AVATAR_FILE_STORAGE, \
|
||||
UNREAD_NOTIFICATIONS_REQUEST_INTERVAL, SHARE_LINK_EXPIRE_DAYS_MIN, \
|
||||
SHARE_LINK_EXPIRE_DAYS_MAX, SHARE_LINK_EXPIRE_DAYS_DEFAULT, \
|
||||
SEAFILE_COLLAB_SERVER, ENABLE_RESET_ENCRYPTED_REPO_PASSWORD, \
|
||||
EXTRA_SHARE_DIALOG_NOTE, EXTRA_APP_BOTTOM_LINKS, EXTRA_ABOUT_DIALOG_LINKS, \
|
||||
DTABLE_WEB_SERVER
|
||||
|
||||
from seahub.wopi.settings import ENABLE_OFFICE_WEB_APP
|
||||
@@ -1158,4 +1159,7 @@ def react_fake_view(request, **kwargs):
|
||||
'folder_perm_enabled': folder_perm_enabled,
|
||||
'file_audit_enabled' : FILE_AUDIT_ENABLED,
|
||||
'custom_nav_items' : json.dumps(CUSTOM_NAV_ITEMS),
|
||||
'extra_share_dialog_note': EXTRA_SHARE_DIALOG_NOTE,
|
||||
'extra_app_bottom_links': EXTRA_APP_BOTTOM_LINKS,
|
||||
'extra_about_dialog_links': EXTRA_ABOUT_DIALOG_LINKS
|
||||
})
|
||||
|
Reference in New Issue
Block a user