mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-16 23:29:49 +00:00
[draft] removed related code & files (#5993)
* [draft] removed related code & files * [draft] removed related code & files
This commit is contained in:
@@ -3,18 +3,15 @@ import ReactDom from 'react-dom';
|
||||
import { Router, navigate } from '@gatsbyjs/reach-router';
|
||||
import MediaQuery from 'react-responsive';
|
||||
import { Modal } from 'reactstrap';
|
||||
import { siteRoot, canAddRepo, isDocs } from './utils/constants';
|
||||
import { siteRoot, canAddRepo } from './utils/constants';
|
||||
import { Utils } from './utils/utils';
|
||||
import SystemNotification from './components/system-notification';
|
||||
import SidePanel from './components/side-panel';
|
||||
import MainPanel from './components/main-panel';
|
||||
import DraftsView from './pages/drafts/drafts-view';
|
||||
import DraftContent from './pages/drafts/draft-content';
|
||||
import FilesActivities from './pages/dashboard/files-activities';
|
||||
import MyFileActivities from './pages/dashboard/my-file-activities';
|
||||
import Starred from './pages/starred/starred';
|
||||
import LinkedDevices from './pages/linked-devices/linked-devices';
|
||||
import editUtilities from './utils/editor-utilities';
|
||||
import ShareAdminLibraries from './pages/share-admin/libraries';
|
||||
import ShareAdminFolders from './pages/share-admin/folders';
|
||||
import ShareAdminShareLinks from './pages/share-admin/share-links';
|
||||
@@ -39,7 +36,6 @@ import './css/search.css';
|
||||
|
||||
const FilesActivitiesWrapper = MainContentWrapper(FilesActivities);
|
||||
const MyFileActivitiesWrapper = MainContentWrapper(MyFileActivities);
|
||||
const DraftsViewWrapper = MainContentWrapper(DraftsView);
|
||||
const StarredWrapper = MainContentWrapper(Starred);
|
||||
const LinkedDevicesWrapper = MainContentWrapper(LinkedDevices);
|
||||
const SharedLibrariesWrapper = MainContentWrapper(SharedLibraries);
|
||||
@@ -55,9 +51,6 @@ class App extends Component {
|
||||
this.state = {
|
||||
isOpen: false,
|
||||
isSidePanelClosed: false,
|
||||
draftCounts: 0,
|
||||
draftList:[],
|
||||
isLoadingDraft: true,
|
||||
currentTab: '/',
|
||||
pathPrefix: [],
|
||||
};
|
||||
@@ -94,33 +87,11 @@ class App extends Component {
|
||||
// navigate to library page http://127.0.0.1:8000/library/34e7fb92-e91d-499d-bcde-c30ea8af9828/
|
||||
this.navigateClientUrlToLib();
|
||||
|
||||
// e.g. from http://127.0.0.1:8000/drafts/reviews/
|
||||
// get reviews
|
||||
// TODO: need refactor later
|
||||
let href = window.location.href.split('/');
|
||||
if (isDocs) {
|
||||
this.getDrafts();
|
||||
}
|
||||
this.setState({currentTab: href[href.length - 2]});
|
||||
}
|
||||
|
||||
getDrafts = () => {
|
||||
editUtilities.listDrafts().then(res => {
|
||||
this.setState({
|
||||
draftCounts: res.data.draft_counts,
|
||||
draftList: res.data.data,
|
||||
isLoadingDraft: false,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
updateDraftsList = (draft_id) => {
|
||||
this.setState({
|
||||
draftCounts: this.state.draftCounts - 1,
|
||||
draftList: this.state.draftList.filter(draft => draft.id != draft_id),
|
||||
});
|
||||
};
|
||||
|
||||
onCloseSidePanel = () => {
|
||||
this.setState({
|
||||
isSidePanelClosed: !this.state.isSidePanelClosed
|
||||
@@ -238,24 +209,12 @@ class App extends Component {
|
||||
<React.Fragment>
|
||||
<SystemNotification />
|
||||
<div id="main">
|
||||
<SidePanel isSidePanelClosed={this.state.isSidePanelClosed} onCloseSidePanel={this.onCloseSidePanel} currentTab={currentTab} tabItemClick={this.tabItemClick} draftCounts={this.state.draftCounts} />
|
||||
<SidePanel isSidePanelClosed={this.state.isSidePanelClosed} onCloseSidePanel={this.onCloseSidePanel} currentTab={currentTab} tabItemClick={this.tabItemClick} />
|
||||
<MainPanel>
|
||||
<Router className="reach-router">
|
||||
{home}
|
||||
<FilesActivitiesWrapper path={siteRoot + 'dashboard'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} />
|
||||
<MyFileActivitiesWrapper path={siteRoot + 'my-activities'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} />
|
||||
<DraftsViewWrapper path={siteRoot + 'drafts'}
|
||||
onShowSidePanel={this.onShowSidePanel}
|
||||
onSearchedClick={this.onSearchedClick}
|
||||
>
|
||||
<DraftContent
|
||||
path='/'
|
||||
getDrafts={this.getDrafts}
|
||||
isLoadingDraft={this.state.isLoadingDraft}
|
||||
draftList={this.state.draftList}
|
||||
updateDraftsList={this.updateDraftsList}
|
||||
/>
|
||||
</DraftsViewWrapper>
|
||||
<StarredWrapper path={siteRoot + 'starred'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} />
|
||||
<LinkedDevicesWrapper path={siteRoot + 'linked-devices'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} />
|
||||
<ShareAdminLibrariesWrapper path={siteRoot + 'share-admin-libs'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} />
|
||||
|
@@ -15,7 +15,6 @@ const MSG_TYPE_REPO_SHARE = 'repo_share';
|
||||
const MSG_TYPE_REPO_SHARE_TO_GROUP = 'repo_share_to_group';
|
||||
const MSG_TYPE_REPO_TRANSFER = 'repo_transfer';
|
||||
const MSG_TYPE_FILE_UPLOADED = 'file_uploaded';
|
||||
const MSG_TYPE_DRAFT_REVIEWER = 'draft_reviewer';
|
||||
// const MSG_TYPE_GUEST_INVITATION_ACCEPTED = 'guest_invitation_accepted';
|
||||
const MSG_TYPE_REPO_MONITOR = 'repo_monitor';
|
||||
const MSG_TYPE_DELETED_FILES = 'deleted_files';
|
||||
@@ -222,22 +221,6 @@ class NoticeItem extends React.Component {
|
||||
return {avatar_url, notice};
|
||||
}
|
||||
|
||||
if (noticeType === MSG_TYPE_DRAFT_REVIEWER) {
|
||||
|
||||
let avatar_url = detail.request_user_avatat_url;
|
||||
|
||||
let fromUser = detail.request_user_name;
|
||||
|
||||
let draftId = detail.draft_id;
|
||||
let draftUrl = siteRoot + 'drafts/' + draftId + '/';
|
||||
|
||||
let notice = gettext('{from_user} has sent you a request for {draft_link}.');
|
||||
let draftLink = '<a href=' + draftUrl + '>' + gettext('Draft') + '#' + draftId + '</a>';
|
||||
notice = notice.replace('{from_user}', fromUser);
|
||||
notice = notice.replace('{draft_link}', draftLink);
|
||||
return {avatar_url, notice};
|
||||
}
|
||||
|
||||
if (noticeType === MSG_TYPE_REPO_MONITOR) {
|
||||
const {
|
||||
op_user_avatar_url: avatar_url,
|
||||
|
@@ -1,146 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { gettext } from '../../utils/constants';
|
||||
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import toaster from '../toast';
|
||||
import UserSelect from '../user-select';
|
||||
import '../../css/add-reviewer-dialog.css';
|
||||
|
||||
const propTypes = {
|
||||
showReviewerDialog: PropTypes.bool.isRequired,
|
||||
draftID: PropTypes.string.isRequired,
|
||||
toggleAddReviewerDialog: PropTypes.func.isRequired,
|
||||
reviewers: PropTypes.array.isRequired
|
||||
};
|
||||
|
||||
class AddReviewerDialog extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
reviewers: this.props.reviewers,
|
||||
selectedOption: null,
|
||||
errorMsg: [],
|
||||
loading: false,
|
||||
};
|
||||
this.Options = [];
|
||||
}
|
||||
|
||||
listReviewers = () => {
|
||||
seafileAPI.listDraftReviewers(this.props.draftID).then((res) => {
|
||||
this.setState({ reviewers: res.data.reviewers });
|
||||
});
|
||||
};
|
||||
|
||||
handleSelectChange = (option) => {
|
||||
this.setState({ selectedOption: option });
|
||||
this.Options = [];
|
||||
};
|
||||
|
||||
addReviewers = () => {
|
||||
if (this.state.selectedOption.length > 0 ) {
|
||||
this.refs.reviewSelect.clearSelect();
|
||||
let reviewers = [];
|
||||
for (let i = 0; i < this.state.selectedOption.length; i ++) {
|
||||
reviewers[i] = this.state.selectedOption[i].email;
|
||||
}
|
||||
this.setState({
|
||||
loading: true,
|
||||
errorMsg: [],
|
||||
});
|
||||
seafileAPI.addDraftReviewers(this.props.draftID, reviewers).then((res) => {
|
||||
if (res.data.failed.length > 0) {
|
||||
let errorMsg = [];
|
||||
for (let i = 0 ; i < res.data.failed.length ; i++) {
|
||||
errorMsg[i] = res.data.failed[i];
|
||||
}
|
||||
this.setState({ errorMsg: errorMsg });
|
||||
}
|
||||
this.setState({
|
||||
selectedOption: null,
|
||||
loading: false
|
||||
});
|
||||
if (res.data.success.length > 0) {
|
||||
this.listReviewers();
|
||||
}
|
||||
}).catch(error => {
|
||||
let errorMsg = Utils.getErrorMsg(error);
|
||||
toaster.danger(errorMsg);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
deleteReviewer = (event) => {
|
||||
let reviewer = event.target.getAttribute('name');
|
||||
seafileAPI.deleteDraftReviewer(this.props.draftID, reviewer).then((res) => {
|
||||
if (res.data === 200) {
|
||||
let newReviewers = [];
|
||||
for (let i = 0; i < this.state.reviewers.length; i ++) {
|
||||
if (this.state.reviewers[i].user_email !== reviewer) {
|
||||
newReviewers.push(this.state.reviewers[i]);
|
||||
}
|
||||
}
|
||||
this.setState({ reviewers: newReviewers });
|
||||
}
|
||||
}).catch(error => {
|
||||
let errorMsg = Utils.getErrorMsg(error);
|
||||
toaster.danger(errorMsg);
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const toggleDialog = this.props.toggleAddReviewerDialog;
|
||||
const { reviewers, errorMsg } = this.state;
|
||||
return (
|
||||
<Modal isOpen={true} toggle={toggleDialog}>
|
||||
<ModalHeader toggle={toggleDialog}>{gettext('Request a review')}</ModalHeader>
|
||||
<ModalBody>
|
||||
<p>{gettext('Add new reviewer')}</p>
|
||||
<div className='add-reviewer'>
|
||||
<UserSelect
|
||||
placeholder={gettext('Search users')}
|
||||
onSelectChange={this.handleSelectChange}
|
||||
ref="reviewSelect"
|
||||
isMulti={true}
|
||||
className='reviewer-select'
|
||||
/>
|
||||
{(this.state.selectedOption && !this.state.loading)?
|
||||
<Button color="secondary" onClick={this.addReviewers}>{gettext('Submit')}</Button> :
|
||||
<Button color="secondary" disabled>{gettext('Submit')}</Button>
|
||||
}
|
||||
</div>
|
||||
{errorMsg.length > 0 &&
|
||||
errorMsg.map((item, index = 0, arr) => {
|
||||
return (
|
||||
<p className="reviewer-select-error error" key={index}>{errorMsg[index].email}
|
||||
{': '}{errorMsg[index].error_msg}</p>
|
||||
);
|
||||
})
|
||||
}
|
||||
{reviewers.length > 0 &&
|
||||
reviewers.map((item, index = 0, arr) => {
|
||||
return (
|
||||
<div className="reviewer-select-info" key={index}>
|
||||
<div className="d-flex">
|
||||
<img className="avatar reviewer-select-avatar" src={item.avatar_url} alt=""/>
|
||||
<span className="reviewer-select-name ellipsis">{item.user_name}</span>
|
||||
</div>
|
||||
<i className="fa fa-times" name={item.user_email} onClick={this.deleteReviewer}></i>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
}
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button color="secondary" onClick={toggleDialog}>{gettext('Close')}</Button>
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
AddReviewerDialog.propTypes = propTypes;
|
||||
|
||||
export default AddReviewerDialog;
|
@@ -18,8 +18,6 @@ class CreateFile extends React.Component {
|
||||
this.state = {
|
||||
parentPath: '',
|
||||
childName: props.fileType || '',
|
||||
isMarkdownDraft: false,
|
||||
isSdocDraft: false,
|
||||
errMessage: '',
|
||||
isSubmitBtnActive: props.fileType.slice(0, -5) ? true : false,
|
||||
};
|
||||
@@ -61,8 +59,7 @@ class CreateFile extends React.Component {
|
||||
this.setState({errMessage: errMessage});
|
||||
} else {
|
||||
let path = this.state.parentPath + newName;
|
||||
const { isMarkdownDraft, isSdocDraft } = this.state;
|
||||
this.props.onAddFile(path, isMarkdownDraft, isSdocDraft);
|
||||
this.props.onAddFile(path);
|
||||
this.props.toggleDialog();
|
||||
}
|
||||
};
|
||||
@@ -74,55 +71,6 @@ class CreateFile extends React.Component {
|
||||
}
|
||||
};
|
||||
|
||||
handleCheck = () => {
|
||||
let pos = this.state.childName.lastIndexOf('.');
|
||||
|
||||
if (this.state.isMarkdownDraft) {
|
||||
// from draft to not draft
|
||||
// case 1, normally, the file name is ended with `(draft)`, like `test(draft).md`
|
||||
// case 2, the file name is not ended with `(draft)`, the user has deleted some characters, like `test(dra.md`
|
||||
let p = this.state.childName.substring(pos-7, pos);
|
||||
let fileName = this.state.childName.substring(0, pos-7);
|
||||
let fileType = this.state.childName.substring(pos);
|
||||
if (p === '(draft)') {
|
||||
// remove `(draft)` from file name
|
||||
this.setState({
|
||||
childName: fileName + fileType,
|
||||
isMarkdownDraft: !this.state.isMarkdownDraft
|
||||
});
|
||||
} else {
|
||||
// don't change file name
|
||||
this.setState({
|
||||
isMarkdownDraft: !this.state.isMarkdownDraft
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.state.isMarkdownDraft) {
|
||||
// from not draft to draft
|
||||
// case 1, test.md ===> test(draft).md
|
||||
// case 2, .md ===> (draft).md
|
||||
// case 3, no '.' in the file name, don't change the file name
|
||||
if (pos > 0) {
|
||||
let fileName = this.state.childName.substring(0, pos);
|
||||
let fileType = this.state.childName.substring(pos);
|
||||
this.setState({
|
||||
childName: fileName + '(draft)' + fileType,
|
||||
isMarkdownDraft: !this.state.isMarkdownDraft
|
||||
});
|
||||
} else if (pos === 0 ) {
|
||||
this.setState({
|
||||
childName: '(draft)' + this.state.childName,
|
||||
isMarkdownDraft: !this.state.isMarkdownDraft
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
isMarkdownDraft: !this.state.isMarkdownDraft
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
checkDuplicatedName = () => {
|
||||
let isDuplicated = this.props.checkDuplicatedName(this.state.childName);
|
||||
return isDuplicated;
|
||||
@@ -134,12 +82,6 @@ class CreateFile extends React.Component {
|
||||
this.newInput.current.setSelectionRange(0,0);
|
||||
};
|
||||
|
||||
toggleMarkSdocDraft = (e) => {
|
||||
this.setState({
|
||||
isSdocDraft: e.target.checked
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { toggleDialog } = this.props;
|
||||
return (
|
||||
@@ -157,21 +99,6 @@ class CreateFile extends React.Component {
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
{/*this.props.fileType == '.md' && isDocs && (
|
||||
<FormGroup check>
|
||||
<Label check>
|
||||
<Input type="checkbox" onChange={this.handleCheck}/>{' '}{gettext('This is a draft')}
|
||||
</Label>
|
||||
</FormGroup>
|
||||
)*/}
|
||||
{/*this.props.fileType == '.sdoc' && (
|
||||
<FormGroup check>
|
||||
<Label check>
|
||||
<Input type="checkbox" checked={isSdocDraft} onChange={this.toggleMarkSdocDraft}/>
|
||||
<span>{gettext('Mark as draft')}</span>
|
||||
</Label>
|
||||
</FormGroup>
|
||||
)*/}
|
||||
</Form>
|
||||
{this.state.errMessage && <Alert color="danger" className="mt-2">{this.state.errMessage}</Alert>}
|
||||
</ModalBody>
|
||||
|
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import moment from 'moment';
|
||||
import { Button, Modal, ModalHeader, ModalBody, ModalFooter, Table } from 'reactstrap';
|
||||
import { gettext, siteRoot, serviceURL } from '../../utils/constants';
|
||||
import { gettext, siteRoot } from '../../utils/constants';
|
||||
import { Utils } from '../../utils/utils';
|
||||
|
||||
const propTypes = {
|
||||
@@ -33,11 +33,8 @@ class ListCreatedFileDialog extends React.Component {
|
||||
{
|
||||
activity.createdFilesList.map((item, index) => {
|
||||
let fileURL = `${siteRoot}lib/${item.repo_id}/file${Utils.encodePath(item.path)}`;
|
||||
if (item.name.endsWith('(draft).md')) {
|
||||
fileURL = serviceURL + '/drafts/' + item.draft_id + '/';
|
||||
}
|
||||
let fileLink = <a href={fileURL} target='_blank' rel="noreferrer">{item.name}</a>;
|
||||
if (item.name.endsWith('(draft).md') && !item.draft_id) {
|
||||
if (item.name.endsWith('(draft).md')) { // be compatible with the existing draft files
|
||||
fileLink = item.name;
|
||||
}
|
||||
return (
|
||||
|
@@ -1,142 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
|
||||
import { gettext, siteRoot } from '../../utils/constants';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import moment from 'moment';
|
||||
import editorUtilities from '../../utils/editor-utilities';
|
||||
import toaster from '../../components/toast';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import Draft from '../../models/draft';
|
||||
|
||||
const propTypes = {
|
||||
repoID: PropTypes.string.isRequired,
|
||||
toggle: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class ListRepoDraftsDialog extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
drafts: [],
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
seafileAPI.listRepoDrafts(this.props.repoID).then(res => {
|
||||
let drafts = res.data.drafts.map(item => {
|
||||
let draft = new Draft(item);
|
||||
return draft;
|
||||
});
|
||||
this.setState({
|
||||
drafts: drafts
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
onDeleteDraftItem = (draft) => {
|
||||
editorUtilities.deleteDraft(draft.id).then(() => {
|
||||
let drafts = this.state.drafts.filter(item => {
|
||||
return item.id !== draft.id;
|
||||
});
|
||||
this.setState({drafts: drafts});
|
||||
let msg = gettext('Successfully deleted draft %(draft)s.');
|
||||
msg = msg.replace('%(draft)s', draft.draftFilePath);
|
||||
toaster.success(msg);
|
||||
}).catch(() => {
|
||||
let msg = gettext('Failed to delete draft %(draft)s.');
|
||||
msg = msg.replace('%(draft)s', draft.draftFilePath);
|
||||
toaster.danger(msg);
|
||||
});
|
||||
};
|
||||
|
||||
toggle = () => {
|
||||
this.props.toggle();
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Modal isOpen={true} toggle={this.toggle}>
|
||||
<ModalHeader toggle={this.toggle}>{gettext('Drafts')}</ModalHeader>
|
||||
<ModalBody className="dialog-list-container">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th width='50%' className="ellipsis">{gettext('Name')}</th>
|
||||
<th width='20%'>{gettext('Owner')}</th>
|
||||
<th width='20%'>{gettext('Last Update')}</th>
|
||||
<th width='10%'></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{this.state.drafts.map((item, index) => {
|
||||
return (
|
||||
<DraftItem
|
||||
key={index}
|
||||
draftItem={item}
|
||||
onDeleteDraftItem={this.onDeleteDraftItem}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button color="secondary" onClick={this.toggle}>{gettext('Close')}</Button>
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ListRepoDraftsDialog.propTypes = propTypes;
|
||||
|
||||
export default ListRepoDraftsDialog;
|
||||
|
||||
const DraftItemPropTypes = {
|
||||
draftItem: PropTypes.object,
|
||||
onDeleteDraftItem: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class DraftItem extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = ({
|
||||
active: false,
|
||||
});
|
||||
}
|
||||
|
||||
onMouseEnter = () => {
|
||||
this.setState({
|
||||
active: true
|
||||
});
|
||||
};
|
||||
|
||||
onMouseLeave = () => {
|
||||
this.setState({
|
||||
active: false
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const draftItem = this.props.draftItem;
|
||||
let href = siteRoot + 'drafts/' + draftItem.id + '/';
|
||||
let className = this.state.active ? 'action-icon sf2-icon-x3' : 'action-icon vh sf2-icon-x3';
|
||||
return (
|
||||
<tr onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>
|
||||
<td className="name">
|
||||
<a href={href} target='_blank' rel="noreferrer">{Utils.getFileName(draftItem.draftFilePath)}</a>
|
||||
</td>
|
||||
<td>{draftItem.ownerNickname}</td>
|
||||
<td>{moment(draftItem.createdStr).fromNow()}</td>
|
||||
<td>
|
||||
<i className={className} onClick={this.props.onDeleteDraftItem.bind(this, draftItem)}></i>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
DraftItem.propTypes = DraftItemPropTypes;
|
@@ -1,32 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { gettext } from '../../utils/constants';
|
||||
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
|
||||
|
||||
const propTypes = {
|
||||
deleteDraft: PropTypes.func.isRequired,
|
||||
useDraft: PropTypes.func.isRequired,
|
||||
localDraftDialog: PropTypes.bool.isRequired,
|
||||
closeDraftDialog: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class LocalDraftDialog extends React.PureComponent {
|
||||
render() {
|
||||
return (
|
||||
<Modal isOpen={true} toggle={this.props.closeDraftDialog}>
|
||||
<ModalHeader toggle={this.props.closeDraftDialog}>{gettext('Local draft')}</ModalHeader>
|
||||
<ModalBody>
|
||||
<p>{gettext('You have an unsaved draft. Do you like to use it?')}</p>
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button color="primary" onClick={this.props.useDraft}>{gettext('Use draft')}</Button>
|
||||
<Button color="secondary" onClick={this.props.deleteDraft}>{gettext('Delete draft')}</Button>
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
LocalDraftDialog.propTypes = propTypes;
|
||||
|
||||
export default LocalDraftDialog;
|
@@ -2,17 +2,12 @@ import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import { gettext, siteRoot } from '../../utils/constants';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import toaster from '../toast';
|
||||
import SeafileMarkdownViewer from '../seafile-markdown-viewer';
|
||||
|
||||
const propTypes = {
|
||||
path: PropTypes.string.isRequired,
|
||||
repoID: PropTypes.string.isRequired,
|
||||
hash: PropTypes.string,
|
||||
isDraft: PropTypes.bool,
|
||||
hasDraft: PropTypes.bool,
|
||||
goDraftPage: PropTypes.func.isRequired,
|
||||
isFileLoading: PropTypes.bool.isRequired,
|
||||
isFileLoadedErr: PropTypes.bool.isRequired,
|
||||
filePermission: PropTypes.string,
|
||||
@@ -40,17 +35,6 @@ class DirColumnFile extends React.Component {
|
||||
window.open(url);
|
||||
};
|
||||
|
||||
onNewDraft = (e) => {
|
||||
e.preventDefault();
|
||||
let { path, repoID } = this.props;
|
||||
seafileAPI.createDraft(repoID, path).then(res => {
|
||||
window.location.href = siteRoot + 'lib/' + res.data.origin_repo_id + '/file' + res.data.draft_file_path + '?mode=edit';
|
||||
}).catch(error => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
};
|
||||
|
||||
onOpenFile = (e) => {
|
||||
e.preventDefault();
|
||||
let { path, repoID } = this.props;
|
||||
@@ -58,11 +42,6 @@ class DirColumnFile extends React.Component {
|
||||
window.open(newUrl, '_blank');
|
||||
};
|
||||
|
||||
goDraftPage = (e) => {
|
||||
e.preventDefault();
|
||||
this.props.goDraftPage();
|
||||
};
|
||||
|
||||
render() {
|
||||
if (this.props.isFileLoadedErr) {
|
||||
return (
|
||||
@@ -84,14 +63,6 @@ class DirColumnFile extends React.Component {
|
||||
<span className='wiki-open-file position-fixed' onClick={this.onOpenFile}>
|
||||
<i className="fas fa-expand-arrows-alt"></i>
|
||||
</span>
|
||||
{(!this.props.isDraft && this.props.hasDraft) &&
|
||||
<div className='seafile-btn-view-review text-center mt-2'>
|
||||
<div className='tag tag-green'>
|
||||
{gettext('This file is in draft stage.')}
|
||||
<span className="ml-2" onClick={this.goDraftPage}>{gettext('View Draft')}</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</Fragment>
|
||||
</SeafileMarkdownViewer>
|
||||
);
|
||||
|
@@ -28,9 +28,6 @@ const propTypes = {
|
||||
isFileLoading: PropTypes.bool.isRequired,
|
||||
isFileLoadedErr: PropTypes.bool.isRequired,
|
||||
hash: PropTypes.string,
|
||||
isDraft: PropTypes.bool.isRequired,
|
||||
hasDraft: PropTypes.bool.isRequired,
|
||||
goDraftPage: PropTypes.func.isRequired,
|
||||
filePermission: PropTypes.string,
|
||||
content: PropTypes.string,
|
||||
lastModified: PropTypes.string,
|
||||
@@ -38,7 +35,6 @@ const propTypes = {
|
||||
onLinkClick: PropTypes.func.isRequired,
|
||||
// repo content
|
||||
isRepoInfoBarShow: PropTypes.bool.isRequired,
|
||||
draftCounts: PropTypes.number.isRequired,
|
||||
usedRepoTags: PropTypes.array.isRequired,
|
||||
updateUsedRepoTags: PropTypes.func.isRequired,
|
||||
// list
|
||||
@@ -181,9 +177,6 @@ class DirColumnView extends React.Component {
|
||||
path={this.props.path}
|
||||
repoID={this.props.repoID}
|
||||
hash={this.props.hash}
|
||||
isDraft={this.props.isDraft}
|
||||
hasDraft={this.props.hasDraft}
|
||||
goDraftPage={this.props.goDraftPage}
|
||||
isFileLoading={this.props.isFileLoading}
|
||||
isFileLoadedErr={this.props.isFileLoadedErr}
|
||||
filePermission={this.props.filePermission}
|
||||
@@ -202,7 +195,6 @@ class DirColumnView extends React.Component {
|
||||
enableDirPrivateShare={this.props.enableDirPrivateShare}
|
||||
isRepoInfoBarShow={this.props.isRepoInfoBarShow}
|
||||
usedRepoTags={this.props.usedRepoTags}
|
||||
draftCounts={this.props.draftCounts}
|
||||
updateUsedRepoTags={this.props.updateUsedRepoTags}
|
||||
isDirentListLoading={this.props.isDirentListLoading}
|
||||
direntList={this.props.direntList}
|
||||
|
@@ -8,7 +8,6 @@ const propTypes = {
|
||||
path: PropTypes.string.isRequired,
|
||||
repoID: PropTypes.string.isRequired,
|
||||
currentRepoInfo: PropTypes.object.isRequired,
|
||||
draftCounts: PropTypes.number,
|
||||
usedRepoTags: PropTypes.array.isRequired,
|
||||
updateUsedRepoTags: PropTypes.func.isRequired,
|
||||
direntList: PropTypes.array.isRequired,
|
||||
@@ -53,7 +52,6 @@ class DirGridView extends React.Component {
|
||||
<RepoInfoBar
|
||||
repoID={this.props.repoID}
|
||||
currentPath={this.props.path}
|
||||
draftCounts={this.props.draftCounts}
|
||||
usedRepoTags={this.props.usedRepoTags}
|
||||
updateUsedRepoTags={this.props.updateUsedRepoTags}
|
||||
onFileTagChanged={this.props.onFileTagChanged}
|
||||
|
@@ -14,7 +14,6 @@ const propTypes = {
|
||||
isRepoInfoBarShow: PropTypes.bool.isRequired,
|
||||
repoTags: PropTypes.array.isRequired,
|
||||
usedRepoTags: PropTypes.array.isRequired,
|
||||
draftCounts: PropTypes.number,
|
||||
updateUsedRepoTags: PropTypes.func.isRequired,
|
||||
isDirentListLoading: PropTypes.bool.isRequired,
|
||||
direntList: PropTypes.array.isRequired,
|
||||
@@ -64,7 +63,6 @@ class DirListView extends React.Component {
|
||||
<RepoInfoBar
|
||||
repoID={this.props.repoID}
|
||||
currentPath={this.props.path}
|
||||
draftCounts={this.props.draftCounts}
|
||||
usedRepoTags={this.props.usedRepoTags}
|
||||
updateUsedRepoTags={this.props.updateUsedRepoTags}
|
||||
onFileTagChanged={this.props.onFileTagChanged}
|
||||
|
@@ -181,12 +181,6 @@ class DirentGridView extends React.Component {
|
||||
case 'Lock':
|
||||
this.onLockItem(currentObject);
|
||||
break;
|
||||
case 'Mark as draft':
|
||||
this.onMarkAsDraft(currentObject);
|
||||
break;
|
||||
case 'Unmark as draft':
|
||||
this.onUnmarkAsDraft(currentObject);
|
||||
break;
|
||||
case 'History':
|
||||
this.onHistory(currentObject);
|
||||
break;
|
||||
@@ -329,28 +323,6 @@ class DirentGridView extends React.Component {
|
||||
});
|
||||
};
|
||||
|
||||
onMarkAsDraft = (currentObject) => {
|
||||
let repoID = this.props.repoID;
|
||||
let filePath = this.getDirentPath(currentObject);
|
||||
seafileAPI.sdocMarkAsDraft(repoID, filePath).then((res) => {
|
||||
this.props.updateDirent(currentObject, 'is_sdoc_draft', true);
|
||||
}).catch(error => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
};
|
||||
|
||||
onUnmarkAsDraft = (currentObject) => {
|
||||
let repoID = this.props.repoID;
|
||||
let filePath = this.getDirentPath(currentObject);
|
||||
seafileAPI.sdocUnmarkAsDraft(repoID, filePath).then((res) => {
|
||||
this.props.updateDirent(currentObject, 'is_sdoc_draft', false);
|
||||
}).catch(error => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
};
|
||||
|
||||
onHistory = (currentObject) => {
|
||||
let repoID = this.props.repoID;
|
||||
let filePath = this.getDirentPath(currentObject);
|
||||
|
@@ -295,12 +295,6 @@ class DirentListItem extends React.Component {
|
||||
case 'Convert to sdoc':
|
||||
this.onItemConvert(event, 'sdoc');
|
||||
break;
|
||||
case 'Mark as draft':
|
||||
this.onMarkAsDraft();
|
||||
break;
|
||||
case 'Unmark as draft':
|
||||
this.onUnmarkAsDraft();
|
||||
break;
|
||||
case 'History':
|
||||
this.onHistory();
|
||||
break;
|
||||
@@ -415,28 +409,6 @@ class DirentListItem extends React.Component {
|
||||
});
|
||||
};
|
||||
|
||||
onMarkAsDraft = () => {
|
||||
let repoID = this.props.repoID;
|
||||
let filePath = this.getDirentPath(this.props.dirent);
|
||||
seafileAPI.sdocMarkAsDraft(repoID, filePath).then((res) => {
|
||||
this.props.updateDirent(this.props.dirent, 'is_sdoc_draft', true);
|
||||
}).catch(error => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
};
|
||||
|
||||
onUnmarkAsDraft = () => {
|
||||
let repoID = this.props.repoID;
|
||||
let filePath = this.getDirentPath(this.props.dirent);
|
||||
seafileAPI.sdocUnmarkAsDraft(repoID, filePath).then((res) => {
|
||||
this.props.updateDirent(this.props.dirent, 'is_sdoc_draft', false);
|
||||
}).catch(error => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
};
|
||||
|
||||
onHistory = () => {
|
||||
let repoID = this.props.repoID;
|
||||
let filePath = this.getDirentPath(this.props.dirent);
|
||||
@@ -779,9 +751,6 @@ class DirentListItem extends React.Component {
|
||||
<a className="sf-link" onClick={this.onItemClick}>{dirent.name}</a> :
|
||||
<a href={dirent.type === 'dir' ? dirHref : fileHref} onClick={this.onItemClick}>{dirent.name}</a>
|
||||
}
|
||||
{/*(Utils.isSdocFile(dirent.name) && dirent.is_sdoc_draft) &&
|
||||
<span className="dirent-sdoc-draft-identifier">{gettext('Draft')}</span>
|
||||
*/}
|
||||
</Fragment>
|
||||
)}
|
||||
</td>
|
||||
|
@@ -1,126 +0,0 @@
|
||||
import React from 'react';
|
||||
import moment from 'moment';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Dropdown, DropdownMenu, DropdownToggle, DropdownItem } from 'reactstrap';
|
||||
import { gettext, siteRoot, lang } from '../../utils/constants';
|
||||
import { Utils } from '../../utils/utils';
|
||||
|
||||
moment.locale(lang);
|
||||
const propTypes = {
|
||||
draft: PropTypes.object.isRequired,
|
||||
isItemFreezed: PropTypes.bool.isRequired,
|
||||
onFreezedItem: PropTypes.func.isRequired,
|
||||
onUnfreezedItem: PropTypes.func.isRequired,
|
||||
onDeleteHandler: PropTypes.func.isRequired,
|
||||
onPublishHandler: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class DraftListItem extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isMenuIconShow: false,
|
||||
isItemMenuShow: false,
|
||||
highlight: false,
|
||||
};
|
||||
}
|
||||
|
||||
onMouseEnter = () => {
|
||||
if (!this.props.isItemFreezed) {
|
||||
this.setState({
|
||||
isMenuIconShow: true,
|
||||
highlight: true,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
onMouseLeave = () => {
|
||||
if (!this.props.isItemFreezed) {
|
||||
this.setState({
|
||||
isMenuIconShow: false,
|
||||
highlight: false,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
onDropdownToggleClick = (e) => {
|
||||
e.preventDefault();
|
||||
this.toggleOperationMenu(e);
|
||||
};
|
||||
|
||||
toggleOperationMenu = (e) => {
|
||||
e.stopPropagation();
|
||||
this.setState(
|
||||
{isItemMenuShow: !this.state.isItemMenuShow }, () => {
|
||||
if (this.state.isItemMenuShow) {
|
||||
this.props.onFreezedItem();
|
||||
} else {
|
||||
this.setState({
|
||||
highlight: false,
|
||||
isMenuIconShow: false,
|
||||
});
|
||||
this.props.onUnfreezedItem();
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
onDeleteHandler = () => {
|
||||
this.props.onDeleteHandler(this.props.draft);
|
||||
};
|
||||
|
||||
onPublishHandler = () => {
|
||||
this.props.onPublishHandler(this.props.draft);
|
||||
};
|
||||
|
||||
render() {
|
||||
let draft = this.props.draft;
|
||||
let repoID = draft.origin_repo_id;
|
||||
let filePath = draft.draft_file_path;
|
||||
let fileName = Utils.getFileName(filePath);
|
||||
let draftUrl = siteRoot + 'drafts/' + draft.id + '/';
|
||||
let libraryUrl = siteRoot + 'library/' + repoID + '/' + encodeURIComponent(draft.repo_name) + '/' ;
|
||||
let localTime = moment.utc(draft.updated_at).toDate();
|
||||
localTime = moment(localTime).fromNow();
|
||||
|
||||
let iconUrl = Utils.getFileIconUrl(fileName);
|
||||
return (
|
||||
<tr className={this.state.highlight ? 'tr-highlight' : ''} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>
|
||||
<td className="text-center"><img src={iconUrl} width="24" alt='' /></td>
|
||||
<td className="name" >
|
||||
<a href={draftUrl} target="_blank" rel="noreferrer">{fileName}</a>
|
||||
</td>
|
||||
<td className="library">
|
||||
<a href={libraryUrl} target="_blank" rel="noreferrer">{draft.repo_name}</a>
|
||||
</td>
|
||||
<td className="update">{localTime}</td>
|
||||
<td className="text-center">
|
||||
{this.state.isMenuIconShow && (
|
||||
<Dropdown isOpen={this.state.isItemMenuShow} toggle={this.toggleOperationMenu}>
|
||||
<DropdownToggle
|
||||
tag="i"
|
||||
className="fas fa-ellipsis-v attr-action-icon"
|
||||
title={gettext('More operations')}
|
||||
aria-label={gettext('More operations')}
|
||||
onClick={this.onDropdownToggleClick}
|
||||
data-toggle="dropdown"
|
||||
aria-expanded={this.state.isItemMenuShow}
|
||||
/>
|
||||
<DropdownMenu>
|
||||
<DropdownItem onClick={this.onDeleteHandler}>{gettext('Delete')}</DropdownItem>
|
||||
{draft.status == 'open' &&
|
||||
<DropdownItem onClick={this.onPublishHandler}>{gettext('Publish')}</DropdownItem>
|
||||
}
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
DraftListItem.propTypes = propTypes;
|
||||
|
||||
export default DraftListItem;
|
@@ -1,64 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { gettext } from '../../utils/constants';
|
||||
import DraftListItem from './draft-list-item';
|
||||
|
||||
const propTypes = {
|
||||
draftList: PropTypes.array.isRequired,
|
||||
onDeleteHandler: PropTypes.func.isRequired,
|
||||
onPublishHandler: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class DraftListView extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isItemFreezed: false,
|
||||
};
|
||||
}
|
||||
|
||||
onFreezedItem = () => {
|
||||
this.setState({isItemFreezed: true});
|
||||
};
|
||||
|
||||
onUnfreezedItem = () => {
|
||||
this.setState({isItemFreezed: false});
|
||||
};
|
||||
|
||||
render() {
|
||||
let drafts = this.props.draftList;
|
||||
return (
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style={{width: '4%'}}>{/*img*/}</th>
|
||||
<th style={{width: '46%'}}>{gettext('Name')}</th>
|
||||
<th style={{width: '30%'}}>{gettext('Library')}</th>
|
||||
<th style={{width: '10%'}}>{gettext('Last Update')}</th>
|
||||
<th style={{width: '10%'}}></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{ drafts && drafts.map((draft) => {
|
||||
return (
|
||||
<DraftListItem
|
||||
key={draft.id}
|
||||
draft={draft}
|
||||
isItemFreezed={this.state.isItemFreezed}
|
||||
onFreezedItem={this.onFreezedItem}
|
||||
onUnfreezedItem={this.onUnfreezedItem}
|
||||
onDeleteHandler={this.props.onDeleteHandler}
|
||||
onPublishHandler={this.props.onPublishHandler}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
DraftListView.propTypes = propTypes;
|
||||
|
||||
export default DraftListView;
|
@@ -12,7 +12,6 @@ import { canViewOrg, isDocs, isPro, isDBSqlite3, customNavItems } from '../utils
|
||||
const propTypes = {
|
||||
currentTab: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
|
||||
tabItemClick: PropTypes.func.isRequired,
|
||||
draftCounts: PropTypes.number,
|
||||
};
|
||||
|
||||
class MainSideNav extends React.Component {
|
||||
@@ -251,15 +250,6 @@ class MainSideNav extends React.Component {
|
||||
<span className="nav-text">{gettext('Published Libraries')}</span>
|
||||
</Link>
|
||||
</li>
|
||||
{/*isDocs &&
|
||||
<li className="nav-item" onClick={(e) => this.tabItemClick(e, 'drafts')}>
|
||||
<Link className={`nav-link ellipsis ${this.getActiveClass('drafts')}`} to={siteRoot + 'drafts/'} title={gettext('Drafts')}>
|
||||
<span className="sf2-icon-edit" aria-hidden="true"></span>
|
||||
<span className="nav-text">{gettext('Drafts')}</span>
|
||||
{this.props.draftCounts > 0 && <span id="draft-num">{this.props.draftCounts}</span>}
|
||||
</Link>
|
||||
</li>
|
||||
*/}
|
||||
<li className="nav-item">
|
||||
<Link className={`nav-link ellipsis ${this.getActiveClass('linked-devices')}`} to={siteRoot + 'linked-devices/'} title={gettext('Linked Devices')} onClick={(e) => this.tabItemClick(e, 'linked-devices')}>
|
||||
<span className="sf2-icon-monitor" aria-hidden="true"></span>
|
||||
|
@@ -2,14 +2,12 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import ModalPortal from './modal-portal';
|
||||
import ListTaggedFilesDialog from './dialog/list-taggedfiles-dialog';
|
||||
import ListRepoDraftsDialog from './dialog/list-repo-drafts-dialog';
|
||||
|
||||
import '../css/repo-info-bar.css';
|
||||
|
||||
const propTypes = {
|
||||
repoID: PropTypes.string.isRequired,
|
||||
usedRepoTags: PropTypes.array.isRequired,
|
||||
draftCounts: PropTypes.number,
|
||||
updateUsedRepoTags: PropTypes.func,
|
||||
onFileTagChanged: PropTypes.func,
|
||||
className: PropTypes.string,
|
||||
@@ -24,7 +22,6 @@ class RepoInfoBar extends React.Component {
|
||||
this.state = {
|
||||
currentTag: null,
|
||||
isListTaggedFileShow: false,
|
||||
showRepoDrafts: false
|
||||
};
|
||||
}
|
||||
|
||||
@@ -41,19 +38,8 @@ class RepoInfoBar extends React.Component {
|
||||
});
|
||||
};
|
||||
|
||||
toggleDrafts = () => {
|
||||
this.setState({
|
||||
showRepoDrafts: !this.state.showRepoDrafts
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
let { repoID, usedRepoTags, draftCounts, className } = this.props;
|
||||
|
||||
// to be compatible with the existing code
|
||||
if (draftCounts === undefined) {
|
||||
draftCounts = 0;
|
||||
}
|
||||
let { repoID, usedRepoTags, className } = this.props;
|
||||
|
||||
return (
|
||||
<div className={`repo-info-bar ${className ? className : ''}`}>
|
||||
@@ -72,17 +58,6 @@ class RepoInfoBar extends React.Component {
|
||||
})}
|
||||
</ul>
|
||||
)}
|
||||
{/*<div className={usedRepoTags.length > 0 ? 'file-info-list mt-1' : 'file-info-list'}>
|
||||
{draftCounts > 0 &&
|
||||
<span className="file-info">
|
||||
<span className="info-icon sf2-icon-drafts"></span>
|
||||
<span className="used-tag-name">{gettext('draft')}</span>
|
||||
<button type="button" className="used-tag-files border-0 bg-transparent" onClick={this.toggleDrafts}>
|
||||
{draftCounts > 1 ? draftCounts + ' files' : draftCounts + ' file'}
|
||||
</button>
|
||||
</span>
|
||||
}
|
||||
</div>*/}
|
||||
{this.state.isListTaggedFileShow && (
|
||||
<ModalPortal>
|
||||
<ListTaggedFilesDialog
|
||||
@@ -97,16 +72,6 @@ class RepoInfoBar extends React.Component {
|
||||
/>
|
||||
</ModalPortal>
|
||||
)}
|
||||
|
||||
{this.state.showRepoDrafts && (
|
||||
<ModalPortal>
|
||||
<ListRepoDraftsDialog
|
||||
toggle={this.toggleDrafts}
|
||||
repoID={this.props.repoID}
|
||||
/>
|
||||
</ModalPortal>
|
||||
)}
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@@ -9,7 +9,6 @@ const propTypes = {
|
||||
currentTab: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
|
||||
onCloseSidePanel: PropTypes.func.isRequired,
|
||||
tabItemClick: PropTypes.func.isRequired,
|
||||
draftCounts: PropTypes.number,
|
||||
};
|
||||
|
||||
class SidePanel extends React.Component {
|
||||
@@ -21,7 +20,7 @@ class SidePanel extends React.Component {
|
||||
<Logo onCloseSidePanel={this.props.onCloseSidePanel}/>
|
||||
</div>
|
||||
<div className="side-panel-center">
|
||||
<MainSideNav tabItemClick={this.props.tabItemClick} currentTab={this.props.currentTab} draftCounts={this.props.draftCounts}/>
|
||||
<MainSideNav tabItemClick={this.props.tabItemClick} currentTab={this.props.currentTab} />
|
||||
</div>
|
||||
<div className="side-panel-footer">
|
||||
<SideNavFooter />
|
||||
|
@@ -126,28 +126,6 @@ class MultipleDirOperationToolbar extends React.Component {
|
||||
});
|
||||
};
|
||||
|
||||
onMarkAsDraft = (dirent) => {
|
||||
let repoID = this.props.repoID;
|
||||
let filePath = this.getDirentPath(dirent);
|
||||
seafileAPI.sdocMarkAsDraft(repoID, filePath).then((res) => {
|
||||
this.props.updateDirent(dirent, 'is_sdoc_draft', true);
|
||||
}).catch(error => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
};
|
||||
|
||||
onUnmarkAsDraft = (dirent) => {
|
||||
let repoID = this.props.repoID;
|
||||
let filePath = this.getDirentPath(dirent);
|
||||
seafileAPI.sdocUnmarkAsDraft(repoID, filePath).then((res) => {
|
||||
this.props.updateDirent(dirent, 'is_sdoc_draft', false);
|
||||
}).catch(error => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
};
|
||||
|
||||
onStartRevise = (dirent) => {
|
||||
let repoID = this.props.repoID;
|
||||
let filePath = this.getDirentPath(dirent);
|
||||
@@ -206,12 +184,6 @@ class MultipleDirOperationToolbar extends React.Component {
|
||||
case 'Unlock':
|
||||
this.unlockFile(dirent);
|
||||
break;
|
||||
case 'Mark as draft':
|
||||
this.onMarkAsDraft(dirent);
|
||||
break;
|
||||
case 'Unmark as draft':
|
||||
this.onUnmarkAsDraft(dirent);
|
||||
break;
|
||||
case 'History':
|
||||
this.onHistory(dirent);
|
||||
break;
|
||||
|
@@ -1,10 +1,8 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { DropdownToggle, Dropdown, DropdownMenu, DropdownItem, Tooltip} from 'reactstrap';
|
||||
import { gettext, siteRoot, isDocs } from '../../utils/constants';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import { DropdownToggle, Dropdown, DropdownMenu, DropdownItem } from 'reactstrap';
|
||||
import { gettext, siteRoot } from '../../utils/constants';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import toaster from '../toast';
|
||||
import ModalPotal from '../modal-portal';
|
||||
import ShareDialog from '../dialog/share-dialog';
|
||||
import EditFileTagDialog from '../dialog/edit-filetag-dialog';
|
||||
@@ -18,8 +16,6 @@ const propTypes = {
|
||||
enableDirPrivateShare: PropTypes.bool.isRequired,
|
||||
isGroupOwnedRepo: PropTypes.bool.isRequired,
|
||||
filePermission: PropTypes.string,
|
||||
isDraft: PropTypes.bool.isRequired,
|
||||
hasDraft: PropTypes.bool.isRequired,
|
||||
fileTags: PropTypes.array.isRequired,
|
||||
onFileTagChanged: PropTypes.func.isRequired,
|
||||
showShareBtn: PropTypes.bool.isRequired,
|
||||
@@ -31,7 +27,6 @@ class ViewFileToolbar extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isDraftMessageShow: false,
|
||||
isMoreMenuShow: false,
|
||||
isShareDialogShow: false,
|
||||
isEditTagDialogShow: false,
|
||||
@@ -45,21 +40,6 @@ class ViewFileToolbar extends React.Component {
|
||||
window.open(url);
|
||||
};
|
||||
|
||||
onNewDraft = (e) => {
|
||||
e.preventDefault();
|
||||
let { path, repoID } = this.props;
|
||||
seafileAPI.createDraft(repoID, path).then(res => {
|
||||
window.location.href = siteRoot + 'lib/' + res.data.origin_repo_id + '/file' + res.data.draft_file_path + '?mode=edit';
|
||||
}).catch(error => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
};
|
||||
|
||||
onDraftHover = () => {
|
||||
this.setState({isDraftMessageShow: !this.state.isDraftMessageShow});
|
||||
};
|
||||
|
||||
toggleMore = () => {
|
||||
this.setState({isMoreMenuShow: !this.state.isMoreMenuShow});
|
||||
};
|
||||
@@ -82,17 +62,11 @@ class ViewFileToolbar extends React.Component {
|
||||
return (
|
||||
<Fragment>
|
||||
<div className="dir-operation">
|
||||
{((filePermission === 'rw' || filePermission === 'cloud-edit') && !this.props.hasDraft) && (
|
||||
{(filePermission === 'rw' || filePermission === 'cloud-edit') && (
|
||||
<Fragment>
|
||||
<button className="btn btn-secondary operation-item" title={gettext('Edit File')} onClick={this.onEditClick}>{gettext('Edit')}</button>
|
||||
</Fragment>
|
||||
)}
|
||||
{(filePermission === 'rw' && !this.props.isDraft && !this.props.hasDraft && isDocs) && (
|
||||
<Fragment>
|
||||
<button id="new-draft" className="btn btn-secondary operation-item" onClick={this.onNewDraft}>{gettext('New Draft')}</button>
|
||||
<Tooltip target="new-draft" placement="bottom" isOpen={this.state.isDraftMessageShow} toggle={this.onDraftHover}>{gettext('Create a draft from this file, instead of editing it directly.')}</Tooltip>
|
||||
</Fragment>
|
||||
)}
|
||||
{filePermission === 'rw' && (
|
||||
<Dropdown isOpen={this.state.isMoreMenuShow} toggle={this.toggleMore}>
|
||||
<DropdownToggle className='btn btn-secondary operation-item'>
|
||||
|
@@ -1,38 +0,0 @@
|
||||
.reviewer-select-info {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.reviewer-select-avatar {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.reviewer-select-name {
|
||||
height: 2rem;
|
||||
line-height: 2rem;
|
||||
}
|
||||
.reviewer-select-error {
|
||||
margin-top: 1em;
|
||||
}
|
||||
.reviewer-select .true__dropdown-indicator, .reviewer-select .true__indicator-separator {
|
||||
display: none;
|
||||
}
|
||||
.reviewer-select-info i {
|
||||
opacity: 0;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.reviewer-select-info:hover i {
|
||||
cursor: pointer;
|
||||
opacity: 1;
|
||||
color: #a4a4a4;
|
||||
}
|
||||
.add-reviewer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.add-reviewer .reviewer-select {
|
||||
width: 385px;
|
||||
}
|
||||
.add-reviewer .btn {
|
||||
width: 75px;
|
||||
}
|
@@ -25,8 +25,6 @@ class Acticity {
|
||||
this.old_name = json.old_name;
|
||||
} else if (json.op_type === 'publish') {
|
||||
this.old_path = json.old_path;
|
||||
} else if (json.name.endsWith('(draft).md')) {
|
||||
this.draft_id = json.draft_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -42,7 +42,6 @@ class Dirent {
|
||||
this.encoded_thumbnail_src = json.encoded_thumbnail_src;
|
||||
}
|
||||
if (Utils.isSdocFile(json.name)) {
|
||||
this.is_sdoc_draft = json.is_sdoc_draft || false;
|
||||
this.is_sdoc_revision = json.is_sdoc_revision || false;
|
||||
this.revision_id = json.revision_id || null;
|
||||
}
|
||||
|
@@ -1,15 +0,0 @@
|
||||
import moment from 'moment';
|
||||
|
||||
class Draft {
|
||||
|
||||
constructor(item) {
|
||||
this.created = item.created_at;
|
||||
this.createdStr = moment((new Date(item.created_at)).getTime()).format('YYYY-MM-DD HH:mm');
|
||||
this.id = item.id;
|
||||
this.ownerNickname = item.owner_nickname;
|
||||
this.originRepoID = item.origin_repo_id;
|
||||
this.draftFilePath = item.draft_file_path;
|
||||
}
|
||||
}
|
||||
|
||||
export default Draft;
|
@@ -1,14 +0,0 @@
|
||||
import moment from 'moment';
|
||||
|
||||
class Review {
|
||||
|
||||
constructor(item) {
|
||||
this.created = item.created_at;
|
||||
this.createdStr = moment((new Date(item.created_at)).getTime()).format('YYYY-MM-DD HH:mm');
|
||||
this.id = item.id;
|
||||
this.creatorName = item.creator_name;
|
||||
this.draftFilePath = item.draft_file_path;
|
||||
}
|
||||
}
|
||||
|
||||
export default Review;
|
@@ -1,7 +1,7 @@
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import moment from 'moment';
|
||||
import { gettext, siteRoot, serviceURL } from '../../utils/constants';
|
||||
import { gettext, siteRoot } from '../../utils/constants';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import ListCreatedFileDialog from '../../components/dialog/list-created-files-dialog';
|
||||
import ModalPortal from '../../components/modal-portal';
|
||||
@@ -70,21 +70,9 @@ class ActivityItem extends Component {
|
||||
moreDetails = true;
|
||||
break;
|
||||
}
|
||||
} else if (item.obj_type == 'draft') {
|
||||
let fileURL = `${siteRoot}lib/${item.repo_id}/file${Utils.encodePath(item.path)}`;
|
||||
let fileLink = <a href={fileURL} target="_blank" rel="noreferrer">{item.name}</a>;
|
||||
op = gettext('Publish draft');
|
||||
details = fileLink;
|
||||
moreDetails = true;
|
||||
} else if (item.obj_type == 'files') {
|
||||
let fileURL = `${siteRoot}lib/${item.repo_id}/file${Utils.encodePath(item.path)}`;
|
||||
if (item.name.endsWith('(draft).md')) {
|
||||
fileURL = serviceURL + '/drafts/' + item.draft_id + '/';
|
||||
}
|
||||
let fileLink = `<a href=${fileURL} target="_blank">${item.name}</a>`;
|
||||
if (item.name.endsWith('(draft).md') && !item.draft_id) {
|
||||
fileLink = item.name;
|
||||
}
|
||||
let fileCount = item.createdFilesCount - 1;
|
||||
let firstLine = gettext('{file} and {n} other files')
|
||||
.replace('{file}', fileLink)
|
||||
@@ -99,10 +87,10 @@ class ActivityItem extends Component {
|
||||
moreDetails = true;
|
||||
} else if (item.obj_type == 'file') {
|
||||
const isDraft = item.name.endsWith('(draft).md');
|
||||
const fileURL = isDraft ? serviceURL + '/drafts/' + item.draft_id + '/' :
|
||||
const fileURL = isDraft ? '' :
|
||||
`${siteRoot}lib/${item.repo_id}/file${Utils.encodePath(item.path)}`;
|
||||
let fileLink = <a href={fileURL} target="_blank" rel="noreferrer">{item.name}</a>;
|
||||
if (isDraft && !item.draft_id) {
|
||||
if (isDraft) {
|
||||
fileLink = item.name;
|
||||
}
|
||||
switch (item.op_type) {
|
||||
|
@@ -1,82 +0,0 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import { gettext } from '../../utils/constants';
|
||||
import editUtilities from '../../utils/editor-utilities';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import PropTypes from 'prop-types';
|
||||
import toaster from '../../components/toast';
|
||||
import EmptyTip from '../../components/empty-tip';
|
||||
import Loading from '../../components/loading';
|
||||
import DraftListView from '../../components/draft-list-view/draft-list-view';
|
||||
|
||||
const propTypes = {
|
||||
isLoadingDraft: PropTypes.bool.isRequired,
|
||||
updateDraftsList: PropTypes.func.isRequired,
|
||||
draftList: PropTypes.array.isRequired,
|
||||
getDrafts: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class DraftContent extends React.Component {
|
||||
|
||||
componentDidMount() {
|
||||
this.props.getDrafts();
|
||||
}
|
||||
|
||||
onDeleteHandler = (draft) => {
|
||||
// let draft = this.state.currentDraft;
|
||||
let draft_name = Utils.getFileName(draft.draft_file_path);
|
||||
editUtilities.deleteDraft(draft.id).then(res => {
|
||||
this.props.updateDraftsList(draft.id);
|
||||
let msg_s = gettext('Successfully deleted draft %(draft)s.');
|
||||
msg_s = msg_s.replace('%(draft)s', draft_name);
|
||||
toaster.success(msg_s);
|
||||
}).catch(() => {
|
||||
let msg_s = gettext('Failed to delete draft %(draft)s.');
|
||||
msg_s = msg_s.replace('%(draft)s', draft_name);
|
||||
toaster.danger(msg_s);
|
||||
});
|
||||
};
|
||||
|
||||
onPublishHandler = (draft) => {
|
||||
// let draft = this.state.currentDraft;
|
||||
let draft_name = Utils.getFileName(draft.draft_file_path);
|
||||
editUtilities.publishDraft(draft.id).then(res => {
|
||||
this.props.updateDraftsList(draft.id);
|
||||
let msg_s = gettext('Successfully published draft %(draft)s.');
|
||||
msg_s = msg_s.replace('%(draft)s', draft_name);
|
||||
toaster.success(msg_s);
|
||||
}).catch(() => {
|
||||
let msg_s = gettext('Failed to publish draft %(draft)s.');
|
||||
msg_s = msg_s.replace('%(draft)s', draft_name);
|
||||
toaster.danger(msg_s);
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="cur-view-content">
|
||||
{this.props.isLoadingDraft && <Loading />}
|
||||
{!this.props.isLoadingDraft && (
|
||||
<Fragment>
|
||||
{this.props.draftList.length === 0 && (
|
||||
<EmptyTip>
|
||||
<h2>{gettext('No draft yet')}</h2>
|
||||
<p>{gettext('Draft is a way to let you collaborate with others on files. You can create a draft from a file, edit the draft and then ask for a review. The original file will be updated only after the draft has been reviewed.')}</p>
|
||||
</EmptyTip>
|
||||
)}
|
||||
{this.props.draftList.length !==0 && (
|
||||
<DraftListView
|
||||
draftList={this.props.draftList}
|
||||
onDeleteHandler={this.onDeleteHandler}
|
||||
onPublishHandler={this.onPublishHandler}
|
||||
/>
|
||||
)}
|
||||
</Fragment>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
DraftContent.propTypes = propTypes;
|
||||
|
||||
export default DraftContent;
|
@@ -1,31 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { gettext } from '../../utils/constants';
|
||||
|
||||
const propTypes = {
|
||||
children: PropTypes.oneOfType([
|
||||
PropTypes.array,
|
||||
PropTypes.object
|
||||
]).isRequired,
|
||||
};
|
||||
|
||||
class DraftsView extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<div className="main-panel-center">
|
||||
<div className="cur-view-container">
|
||||
<div className="cur-view-path">
|
||||
<div className="path-container">
|
||||
<h3 className="sf-heading">{gettext('Drafts')}</h3>
|
||||
</div>
|
||||
</div>
|
||||
{this.props.children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
DraftsView.propTypes = propTypes;
|
||||
|
||||
export default DraftsView;
|
@@ -28,10 +28,7 @@ const propTypes = {
|
||||
isViewFile: PropTypes.bool.isRequired,
|
||||
isFileLoadedErr: PropTypes.bool.isRequired,
|
||||
hash: PropTypes.string,
|
||||
isDraft: PropTypes.bool.isRequired,
|
||||
hasDraft: PropTypes.bool.isRequired,
|
||||
fileTags: PropTypes.array.isRequired,
|
||||
goDraftPage: PropTypes.func.isRequired,
|
||||
isFileLoading: PropTypes.bool.isRequired,
|
||||
filePermission: PropTypes.string,
|
||||
content: PropTypes.string,
|
||||
@@ -50,7 +47,6 @@ const propTypes = {
|
||||
onAddFileNode: PropTypes.func.isRequired,
|
||||
onAddFolderNode: PropTypes.func.isRequired,
|
||||
// repo content
|
||||
draftCounts: PropTypes.number,
|
||||
repoTags: PropTypes.array.isRequired,
|
||||
usedRepoTags: PropTypes.array.isRequired,
|
||||
updateUsedRepoTags: PropTypes.func.isRequired,
|
||||
@@ -164,10 +160,10 @@ class LibContentContainer extends React.Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
let { path, repoID, usedRepoTags, draftCounts } = this.props;
|
||||
let { path, repoID, usedRepoTags } = this.props;
|
||||
let isRepoInfoBarShow = false;
|
||||
if (path === '/') {
|
||||
if (usedRepoTags.length !== 0 || draftCounts !== 0) {
|
||||
if (usedRepoTags.length !== 0) {
|
||||
isRepoInfoBarShow = true;
|
||||
}
|
||||
}
|
||||
@@ -214,7 +210,6 @@ class LibContentContainer extends React.Component {
|
||||
isRepoInfoBarShow={isRepoInfoBarShow}
|
||||
repoTags={this.props.repoTags}
|
||||
usedRepoTags={this.props.usedRepoTags}
|
||||
draftCounts={this.props.draftCounts}
|
||||
updateUsedRepoTags={this.props.updateUsedRepoTags}
|
||||
isDirentListLoading={this.props.isDirentListLoading}
|
||||
direntList={this.props.direntList}
|
||||
@@ -256,7 +251,6 @@ class LibContentContainer extends React.Component {
|
||||
isRepoInfoBarShow={isRepoInfoBarShow}
|
||||
repoTags={this.props.repoTags}
|
||||
usedRepoTags={this.props.usedRepoTags}
|
||||
draftCounts={this.props.draftCounts}
|
||||
updateUsedRepoTags={this.props.updateUsedRepoTags}
|
||||
isDirentListLoading={this.props.isDirentListLoading}
|
||||
direntList={this.props.direntList}
|
||||
@@ -298,9 +292,6 @@ class LibContentContainer extends React.Component {
|
||||
isFileLoading={this.props.isFileLoading}
|
||||
isFileLoadedErr={this.props.isFileLoadedErr}
|
||||
hash={this.props.hash}
|
||||
isDraft={this.props.isDraft}
|
||||
hasDraft={this.props.hasDraft}
|
||||
goDraftPage={this.props.goDraftPage}
|
||||
filePermission={this.props.filePermission}
|
||||
content={this.props.content}
|
||||
lastModified={this.props.lastModified}
|
||||
@@ -309,7 +300,6 @@ class LibContentContainer extends React.Component {
|
||||
isRepoInfoBarShow={isRepoInfoBarShow}
|
||||
repoTags={this.props.repoTags}
|
||||
usedRepoTags={this.props.usedRepoTags}
|
||||
draftCounts={this.props.draftCounts}
|
||||
updateUsedRepoTags={this.props.updateUsedRepoTags}
|
||||
isDirentListLoading={this.props.isDirentListLoading}
|
||||
direntList={this.props.direntList}
|
||||
|
@@ -11,8 +11,6 @@ import { Utils } from '../../utils/utils';
|
||||
const propTypes = {
|
||||
isViewFile: PropTypes.bool.isRequired,
|
||||
filePermission: PropTypes.string,
|
||||
isDraft: PropTypes.bool.isRequired,
|
||||
hasDraft: PropTypes.bool.isRequired,
|
||||
fileTags: PropTypes.array.isRequired,
|
||||
onFileTagChanged: PropTypes.func.isRequired, // for file-view-toolbar
|
||||
// side-panel
|
||||
@@ -73,8 +71,6 @@ class LibContentToolbar extends React.Component {
|
||||
enableDirPrivateShare={this.props.enableDirPrivateShare}
|
||||
isGroupOwnedRepo={this.props.isGroupOwnedRepo}
|
||||
filePermission={this.props.filePermission}
|
||||
isDraft={this.props.isDraft}
|
||||
hasDraft={this.props.hasDraft}
|
||||
fileTags={this.props.fileTags}
|
||||
onFileTagChanged={this.props.onFileTagChanged}
|
||||
showShareBtn={this.props.showShareBtn}
|
||||
|
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
||||
import cookie from 'react-cookies';
|
||||
import moment from 'moment';
|
||||
import { navigate } from '@gatsbyjs/reach-router';
|
||||
import { gettext, siteRoot, username, isDocs, enableVideoThumbnail } from '../../utils/constants';
|
||||
import { gettext, siteRoot, username, enableVideoThumbnail } from '../../utils/constants';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import collabServer from '../../utils/collab-server';
|
||||
@@ -46,11 +46,7 @@ class LibContentView extends React.Component {
|
||||
isGroupOwnedRepo: false,
|
||||
userPerm: '',
|
||||
selectedDirentList: [],
|
||||
isDraft: false,
|
||||
hasDraft: false,
|
||||
fileTags: [],
|
||||
draftID: '',
|
||||
draftCounts: 0,
|
||||
repoTags: [],
|
||||
usedRepoTags: [],
|
||||
isTreeDataLoading: true,
|
||||
@@ -296,7 +292,7 @@ class LibContentView extends React.Component {
|
||||
|
||||
// update data
|
||||
seafileAPI.getFileInfo(repoID, filePath).then((res) => {
|
||||
let { mtime, permission, last_modifier_name, is_draft, has_draft, draft_id } = res.data;
|
||||
let { mtime, permission, last_modifier_name } = res.data;
|
||||
seafileAPI.getFileDownloadLink(repoID, filePath).then((res) => {
|
||||
seafileAPI.getFileContent(res.data).then((res) => {
|
||||
if (this.state.content !== res.data) {
|
||||
@@ -309,9 +305,6 @@ class LibContentView extends React.Component {
|
||||
lastModified: moment.unix(mtime).fromNow(),
|
||||
isFileLoading: false,
|
||||
isFileLoadedErr: false,
|
||||
isDraft: is_draft,
|
||||
hasDraft: has_draft,
|
||||
draftID: draft_id
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -333,18 +326,6 @@ class LibContentView extends React.Component {
|
||||
// list used FileTags
|
||||
this.updateUsedRepoTags();
|
||||
|
||||
// list draft counts and review counts
|
||||
if (isDocs) {
|
||||
seafileAPI.getRepoDraftCounts(repoID).then(res => {
|
||||
this.setState({
|
||||
draftCounts: res.data.draft_counts,
|
||||
});
|
||||
}).catch(error => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
}
|
||||
|
||||
if (Utils.isMarkdownFile(path)) {
|
||||
seafileAPI.getFileInfo(this.props.repoID, path).then(() => {
|
||||
if (this.state.currentMode !== 'column') {
|
||||
@@ -441,7 +422,7 @@ class LibContentView extends React.Component {
|
||||
|
||||
// update data
|
||||
seafileAPI.getFileInfo(repoID, filePath).then((res) => {
|
||||
let { mtime, permission, last_modifier_name, is_draft, has_draft, draft_id } = res.data;
|
||||
let { mtime, permission, last_modifier_name } = res.data;
|
||||
seafileAPI.getFileDownloadLink(repoID, filePath).then((res) => {
|
||||
seafileAPI.getFileContent(res.data).then((res) => {
|
||||
this.setState({
|
||||
@@ -451,9 +432,6 @@ class LibContentView extends React.Component {
|
||||
lastModified: moment.unix(mtime).fromNow(),
|
||||
isFileLoading: false,
|
||||
isFileLoadedErr: false,
|
||||
isDraft: is_draft,
|
||||
hasDraft: has_draft,
|
||||
draftID: draft_id
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -897,26 +875,15 @@ class LibContentView extends React.Component {
|
||||
});
|
||||
};
|
||||
|
||||
onAddFile = (filePath, isMarkdownDraft, isSdocDraft) => {
|
||||
onAddFile = (filePath) => {
|
||||
let repoID = this.props.repoID;
|
||||
seafileAPI.createFile(repoID, filePath, isMarkdownDraft).then(res => {
|
||||
seafileAPI.createFile(repoID, filePath).then(res => {
|
||||
let name = Utils.getFileName(filePath);
|
||||
let parentPath = Utils.getDirName(filePath);
|
||||
if (this.state.currentMode === 'column') {
|
||||
this.addNodeToTree(name, parentPath, 'file');
|
||||
}
|
||||
if (parentPath === this.state.path && !this.state.isViewFile) {
|
||||
if (isSdocDraft) { // the new file is marked to be draft
|
||||
seafileAPI.sdocMarkAsDraft(repoID, filePath).then((res) => {
|
||||
this.addDirent(name, 'file', res.data.size, isSdocDraft);
|
||||
}).catch(error => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
this.addDirent(name, 'file', res.data.size);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this.addDirent(name, 'file', res.data.size);
|
||||
}
|
||||
}).catch((error) => {
|
||||
@@ -1470,8 +1437,8 @@ class LibContentView extends React.Component {
|
||||
}
|
||||
};
|
||||
|
||||
addDirent = (name, type, size, isSdocDraft) => {
|
||||
let item = this.createDirent(name, type, size, isSdocDraft);
|
||||
addDirent = (name, type, size) => {
|
||||
let item = this.createDirent(name, type, size);
|
||||
let direntList = this.state.direntList;
|
||||
if (type === 'dir') {
|
||||
direntList.unshift(item);
|
||||
@@ -1810,14 +1777,11 @@ class LibContentView extends React.Component {
|
||||
return new TreeNode({object});
|
||||
}
|
||||
|
||||
createDirent(name, type, size, isSdocDraft) {
|
||||
createDirent(name, type, size) {
|
||||
// use current dirent parent's permission as it's permission
|
||||
const { userPerm: permission } = this.state;
|
||||
const mtime = new Date().getTime()/1000;
|
||||
const obj = { name, type, mtime, size, permission };
|
||||
if (isSdocDraft) {
|
||||
obj.is_sdoc_draft = isSdocDraft;
|
||||
}
|
||||
const dirent = new Dirent(obj);
|
||||
return dirent;
|
||||
}
|
||||
@@ -1903,10 +1867,6 @@ class LibContentView extends React.Component {
|
||||
}
|
||||
};
|
||||
|
||||
goDraftPage = () => {
|
||||
window.open(siteRoot + 'drafts/' + this.state.draftID + '/');
|
||||
};
|
||||
|
||||
sortItems = (sortBy, sortOrder) => {
|
||||
cookie.save('seafile-repo-dir-sort-by', sortBy);
|
||||
cookie.save('seafile-repo-dir-sort-order', sortOrder);
|
||||
@@ -2043,8 +2003,6 @@ class LibContentView extends React.Component {
|
||||
<LibContentToolbar
|
||||
isViewFile={this.state.isViewFile}
|
||||
filePermission={this.state.filePermission}
|
||||
isDraft={this.state.isDraft}
|
||||
hasDraft={this.state.hasDraft}
|
||||
fileTags={this.state.fileTags}
|
||||
onFileTagChanged={this.onToolbarFileTagChanged}
|
||||
onSideNavMenuClick={this.props.onMenuClick}
|
||||
@@ -2095,10 +2053,7 @@ class LibContentView extends React.Component {
|
||||
onMainNavBarClick={this.onMainNavBarClick}
|
||||
isViewFile={this.state.isViewFile}
|
||||
hash={this.state.hash}
|
||||
isDraft={this.state.isDraft}
|
||||
hasDraft={this.state.hasDraft}
|
||||
fileTags={this.state.fileTags}
|
||||
goDraftPage={this.goDraftPage}
|
||||
isFileLoading={this.state.isFileLoading}
|
||||
isFileLoadedErr={this.state.isFileLoadedErr}
|
||||
filePermission={this.state.filePermission}
|
||||
@@ -2116,7 +2071,6 @@ class LibContentView extends React.Component {
|
||||
onAddFileNode={this.onAddFile}
|
||||
onRenameNode={this.onRenameTreeNode}
|
||||
onDeleteNode={this.onDeleteTreeNode}
|
||||
draftCounts={this.state.draftCounts}
|
||||
repoTags={this.state.repoTags}
|
||||
usedRepoTags={this.state.usedRepoTags}
|
||||
updateUsedRepoTags={this.updateUsedRepoTags}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import { Utils } from '../../utils/utils';
|
||||
|
||||
const { repoID, repoName, filePath, fileName, draftID } = window.app.pageOptions;
|
||||
const { repoID, repoName, filePath, fileName } = window.app.pageOptions;
|
||||
const { serviceUrl } = window.app.config;
|
||||
const userInfo = window.app.userInfo;
|
||||
const userName = userInfo.username;
|
||||
@@ -137,10 +137,6 @@ class EditorApi {
|
||||
return seafileAPI.deleteShareLink(token);
|
||||
}
|
||||
|
||||
getDraftKey() {
|
||||
return (repoID + filePath);
|
||||
}
|
||||
|
||||
getFileContent(url) {
|
||||
return seafileAPI.getFileContent(url);
|
||||
}
|
||||
@@ -157,22 +153,6 @@ class EditorApi {
|
||||
return seafileAPI.getUserAvatar(userName, size);
|
||||
}
|
||||
|
||||
goDraftPage() {
|
||||
window.location.href = serviceUrl + '/drafts/' + draftID + '/';
|
||||
}
|
||||
|
||||
createDraftFile() {
|
||||
return seafileAPI.createDraft(repoID, filePath).then(res => {
|
||||
window.location.href = serviceUrl + '/lib/' + res.data.origin_repo_id + '/file' + Utils.encodePath(res.data.draft_file_path) + '?mode=edit';
|
||||
});
|
||||
}
|
||||
|
||||
publishDraftFile() {
|
||||
return seafileAPI.publishDraft(draftID).then(res => {
|
||||
window.location.href = serviceUrl + '/lib/' + repoID + '/file' + Utils.encodePath(res.data.published_file_path);
|
||||
});
|
||||
}
|
||||
|
||||
fileMetaData() {
|
||||
return seafileAPI.fileMetaData(repoID, filePath);
|
||||
}
|
||||
|
@@ -37,9 +37,6 @@ class FileInfo extends React.PureComponent {
|
||||
<div className="file-state">
|
||||
<span className={'file-modifier-name'}>{fileInfo.lastModifier}</span>
|
||||
<span className={'file-modifier-time'}>{modifyTime}</span>
|
||||
{this.props.showDraftSaved && (
|
||||
<span className={'file-modifier-savedraft'}>{gettext('Local draft saved')}</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -52,7 +49,6 @@ FileInfo.propTypes = {
|
||||
isLocked: PropTypes.bool,
|
||||
mediaUrl: PropTypes.string,
|
||||
toggleStar: PropTypes.func,
|
||||
showDraftSaved: PropTypes.bool,
|
||||
};
|
||||
|
||||
export default FileInfo;
|
||||
|
@@ -13,15 +13,11 @@ const { seafileCollabServer } = window.app.config;
|
||||
const { canDownloadFile } = window.app.pageOptions;
|
||||
|
||||
const propTypes = {
|
||||
isDocs: PropTypes.bool.isRequired,
|
||||
hasDraft: PropTypes.bool.isRequired,
|
||||
isDraft: PropTypes.bool.isRequired,
|
||||
editorApi: PropTypes.object.isRequired,
|
||||
collabUsers: PropTypes.array.isRequired,
|
||||
fileInfo: PropTypes.object.isRequired,
|
||||
toggleShareLinkDialog: PropTypes.func.isRequired,
|
||||
onEdit: PropTypes.func.isRequired,
|
||||
toggleNewDraft: PropTypes.func.isRequired,
|
||||
toggleStar: PropTypes.func.isRequired,
|
||||
openDialogs: PropTypes.func.isRequired,
|
||||
showFileHistory: PropTypes.bool.isRequired,
|
||||
@@ -31,7 +27,6 @@ const propTypes = {
|
||||
contentChanged: PropTypes.bool.isRequired,
|
||||
saving: PropTypes.bool.isRequired,
|
||||
onSaveEditorContent: PropTypes.func.isRequired,
|
||||
showDraftSaved: PropTypes.bool.isRequired,
|
||||
isLocked: PropTypes.bool.isRequired,
|
||||
lockedByMe: PropTypes.bool.isRequired,
|
||||
toggleLockFile: PropTypes.func.isRequired,
|
||||
@@ -68,7 +63,6 @@ class HeaderToolbar extends React.Component {
|
||||
toggleStar={this.props.toggleStar}
|
||||
editorApi={this.props.editorApi}
|
||||
fileInfo={this.props.fileInfo}
|
||||
showDraftSaved={this.props.showDraftSaved}
|
||||
isLocked={isLocked}
|
||||
isPro={isPro}
|
||||
mediaUrl={mediaUrl}
|
||||
@@ -154,7 +148,6 @@ class HeaderToolbar extends React.Component {
|
||||
toggleStar={this.props.toggleStar}
|
||||
editorApi={this.props.editorApi}
|
||||
fileInfo={this.props.fileInfo}
|
||||
showDraftSaved={this.props.showDraftSaved}
|
||||
/>
|
||||
<div className="topbar-btn-container">
|
||||
<ButtonGroup>
|
||||
|
@@ -3,7 +3,7 @@ import io from 'socket.io-client';
|
||||
import { EXTERNAL_EVENTS, EventBus, RichMarkdownEditor } from '@seafile/seafile-editor';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import { gettext, isDocs, mediaUrl } from '../../utils/constants';
|
||||
import { gettext, mediaUrl } from '../../utils/constants';
|
||||
import toaster from '../../components/toast';
|
||||
import ShareDialog from '../../components/dialog/share-dialog';
|
||||
import InsertFileDialog from '../../components/dialog/insert-file-dialog';
|
||||
@@ -16,7 +16,7 @@ import './css/markdown-editor.css';
|
||||
const CryptoJS = require('crypto-js');
|
||||
const URL = require('url-parse');
|
||||
|
||||
const { repoID, filePath, fileName, isDraft, hasDraft, isLocked, lockedByMe } = window.app.pageOptions;
|
||||
const { repoID, filePath, fileName, isLocked, lockedByMe } = window.app.pageOptions;
|
||||
const { siteRoot, serviceUrl, seafileCollabServer } = window.app.config;
|
||||
const userInfo = window.app.userInfo;
|
||||
const IMAGE_SUFFIXES = ['png', 'PNG', 'jpg', 'JPG', 'jpeg', 'JPEG', 'gif', 'GIF'];
|
||||
@@ -42,11 +42,9 @@ class MarkdownEditor extends React.Component {
|
||||
},
|
||||
editorMode: 'rich',
|
||||
collabServer: seafileCollabServer ? seafileCollabServer : null,
|
||||
localDraftDialog: false,
|
||||
showMarkdownEditorDialog: false,
|
||||
showShareLinkDialog: false,
|
||||
showInsertFileDialog: false,
|
||||
showDraftSaved: false,
|
||||
collabUsers: userInfo ?
|
||||
[{user: userInfo, is_editing: false}] : [],
|
||||
value: null,
|
||||
@@ -61,10 +59,6 @@ class MarkdownEditor extends React.Component {
|
||||
};
|
||||
|
||||
this.timer = null;
|
||||
this.localDraft = '';
|
||||
this.autoSave = false;
|
||||
this.draftRichValue = '';
|
||||
this.draftPlainValue = '';
|
||||
|
||||
if (this.state.collabServer) {
|
||||
const socket = io(this.state.collabServer);
|
||||
@@ -179,50 +173,6 @@ class MarkdownEditor extends React.Component {
|
||||
this.setState({editorMode: editorMode});
|
||||
};
|
||||
|
||||
setDraftValue = (type, value) => {
|
||||
if (type === 'rich') {
|
||||
this.draftRichValue = value;
|
||||
} else {
|
||||
this.draftPlainValue = value;
|
||||
}
|
||||
};
|
||||
|
||||
checkDraft = () => {
|
||||
let draftKey = editorApi.getDraftKey();
|
||||
let draft = localStorage.getItem(draftKey);
|
||||
let that = this;
|
||||
if (draft) {
|
||||
that.setState({localDraftDialog: true});
|
||||
that.localDraft = draft;
|
||||
localStorage.removeItem(draftKey);
|
||||
}
|
||||
};
|
||||
|
||||
useDraft = () => {
|
||||
this.setState({
|
||||
localDraftDialog: false,
|
||||
loading: false,
|
||||
markdownContent: this.localDraft,
|
||||
editorMode: 'rich',
|
||||
});
|
||||
this.emitSwitchEditor(true);
|
||||
};
|
||||
|
||||
deleteDraft = () => {
|
||||
if (this.state.localDraftDialog) {
|
||||
this.setState({
|
||||
localDraftDialog: false,
|
||||
loading: false,
|
||||
});
|
||||
}
|
||||
let draftKey = editorApi.getDraftKey();
|
||||
localStorage.removeItem(draftKey);
|
||||
};
|
||||
|
||||
closeDraftDialog = () => {
|
||||
this.setState({localDraftDialog: false});
|
||||
};
|
||||
|
||||
clearTimer = () => {
|
||||
clearTimeout(this.timer);
|
||||
this.timer = null;
|
||||
@@ -279,16 +229,13 @@ class MarkdownEditor extends React.Component {
|
||||
|
||||
// Goto rich edit page
|
||||
// First, the user has the relevant permissions, otherwise he can only enter the viewer interface or cannot access
|
||||
// case1: If file is draft file
|
||||
// case2: If mode == 'edit' and the file has no draft
|
||||
// case3: The length of markDownContent is 1 when clear all content in editor and the file has no draft
|
||||
const { fileInfo } = this.state;
|
||||
this.setState({
|
||||
loading: false,
|
||||
fileInfo: {...fileInfo, mtime, size, starred, permission, lastModifier, id},
|
||||
markdownContent,
|
||||
value: '',
|
||||
readOnly: !hasPermission || hasDraft,
|
||||
readOnly: !hasPermission,
|
||||
});
|
||||
|
||||
if (userInfo && this.socket) {
|
||||
@@ -309,7 +256,6 @@ class MarkdownEditor extends React.Component {
|
||||
},
|
||||
});
|
||||
}
|
||||
this.checkDraft();
|
||||
this.listFileTags();
|
||||
|
||||
this.listFileParticipants();
|
||||
@@ -480,9 +426,6 @@ class MarkdownEditor extends React.Component {
|
||||
return (
|
||||
<Fragment>
|
||||
<HeaderToolbar
|
||||
isDocs={isDocs}
|
||||
hasDraft={hasDraft}
|
||||
isDraft={isDraft}
|
||||
editorApi={editorApi}
|
||||
collabUsers={this.state.collabUsers}
|
||||
fileInfo={this.state.fileInfo}
|
||||
@@ -490,7 +433,6 @@ class MarkdownEditor extends React.Component {
|
||||
openDialogs={this.openDialogs}
|
||||
toggleShareLinkDialog={this.toggleShareLinkDialog}
|
||||
onEdit={this.setEditorMode}
|
||||
toggleNewDraft={editorApi.createDraftFile}
|
||||
showFileHistory={this.state.isShowHistory ? false : true }
|
||||
toggleHistory={this.toggleHistory}
|
||||
readOnly={this.state.readOnly}
|
||||
@@ -498,7 +440,6 @@ class MarkdownEditor extends React.Component {
|
||||
contentChanged={this.state.contentChanged}
|
||||
saving={this.state.saving}
|
||||
onSaveEditorContent={this.onSaveEditorContent}
|
||||
showDraftSaved={this.state.showDraftSaved}
|
||||
isLocked={this.state.isLocked}
|
||||
lockedByMe={this.state.lockedByMe}
|
||||
toggleLockFile={this.toggleLockFile}
|
||||
|
@@ -1,125 +0,0 @@
|
||||
/* eslint-disable linebreak-style */
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Loading from '../../components/loading';
|
||||
import moment from 'moment';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import { draftRepoID, draftFilePath } from '../../utils/constants';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import toaster from '../../components/toast';
|
||||
|
||||
import '../../css/file-history.css';
|
||||
|
||||
moment.locale(window.app.config.lang);
|
||||
|
||||
class HistoryList extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.perPage = 25;
|
||||
this.state = {
|
||||
currentPage: 1,
|
||||
loading: false
|
||||
};
|
||||
}
|
||||
|
||||
onClick = (event, key, preItem, currentItem)=> {
|
||||
if (key === this.state.activeItem) return false;
|
||||
this.props.onHistoryItemClick(currentItem, preItem, key);
|
||||
};
|
||||
|
||||
onScroll = (event) => {
|
||||
const clientHeight = event.target.clientHeight;
|
||||
const scrollHeight = event.target.scrollHeight;
|
||||
const scrollTop = event.target.scrollTop;
|
||||
const isBottom = (clientHeight + scrollTop + 1 >= scrollHeight);
|
||||
if (isBottom) {
|
||||
if (this.props.totalReversionCount > this.perPage * this.state.currentPage) {
|
||||
let currentPage = this.state.currentPage + 1;
|
||||
this.setState({
|
||||
currentPage: currentPage,
|
||||
loading : true
|
||||
});
|
||||
seafileAPI.listFileHistoryRecords(draftRepoID, draftFilePath, currentPage, this.perPage).then((res) => {
|
||||
let currentHistoryList = Object.assign([], this.props.historyList);
|
||||
this.props.onHistoryListChange([...currentHistoryList, ...res.data.data]);
|
||||
this.setState({
|
||||
loading : false
|
||||
});
|
||||
}).catch(error => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="history-body">
|
||||
<ul onScroll={this.onScroll} className={'history-list-container'}>
|
||||
{
|
||||
this.props.historyList ?
|
||||
this.props.historyList.map((item, index = 0, arr) => {
|
||||
let preItemIndex = index + 1;
|
||||
if (preItemIndex === arr.length) {
|
||||
preItemIndex = index;
|
||||
}
|
||||
return (
|
||||
<HistoryItem
|
||||
onClick={this.onClick}
|
||||
ctime={item.ctime}
|
||||
className={this.props.activeItem === index ? 'item-active': ''}
|
||||
name={item.creator_name}
|
||||
index={index}
|
||||
key={index}
|
||||
preItem={arr[preItemIndex]}
|
||||
currentItem={item}
|
||||
/>
|
||||
);
|
||||
}) : <Loading/>
|
||||
}
|
||||
{
|
||||
this.state.loading &&
|
||||
<li className={'reloading-reversion'}><Loading /></li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class HistoryItem extends React.Component {
|
||||
render() {
|
||||
let time = moment.parseZone(this.props.ctime).format('YYYY-MM-DD HH:mm');
|
||||
return (
|
||||
<li onClick={(event) => this.props.onClick(event, this.props.index, this.props.preItem, this.props.currentItem)} className={'history-list-item ' + this.props.className}>
|
||||
<div className="history-info">
|
||||
<div className="time">{time}</div>
|
||||
<div className="owner"><i className="squire-icon"/><span>{this.props.name}</span></div>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
HistoryItem.propTypes = {
|
||||
index: PropTypes.number.isRequired,
|
||||
currentItem: PropTypes.object.isRequired,
|
||||
onClick: PropTypes.func.isRequired,
|
||||
ctime: PropTypes.string.isRequired,
|
||||
className: PropTypes.string.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
preItem: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
HistoryList.propTypes = {
|
||||
historyList: PropTypes.array.isRequired,
|
||||
onHistoryItemClick: PropTypes.func.isRequired,
|
||||
onHistoryListChange: PropTypes.func.isRequired,
|
||||
totalReversionCount: PropTypes.number.isRequired,
|
||||
activeItem: PropTypes.object.isRequired,
|
||||
index: PropTypes.number.isRequired,
|
||||
};
|
||||
|
||||
export default HistoryList;
|
@@ -17,7 +17,6 @@ const propTypes = {
|
||||
direntList: PropTypes.array.isRequired,
|
||||
dirPath: PropTypes.string.isRequired,
|
||||
toggleStar: PropTypes.func.isRequired,
|
||||
unmarkDraft: PropTypes.func.isRequired,
|
||||
onNewNotification: PropTypes.func.isRequired,
|
||||
onClearNotification: PropTypes.func.isRequired
|
||||
};
|
||||
@@ -39,7 +38,6 @@ class ExternalOperations extends React.Component {
|
||||
const eventBus = EventBus.getInstance();
|
||||
this.unsubscribeInternalLinkEvent = eventBus.subscribe(EXTERNAL_EVENT.INTERNAL_LINK_CLICK, this.onInternalLinkToggle);
|
||||
this.unsubscribeStar = eventBus.subscribe(EXTERNAL_EVENT.TOGGLE_STAR, this.toggleStar);
|
||||
this.unsubscribeUnmark = eventBus.subscribe(EXTERNAL_EVENT.UNMARK_AS_DRAFT, this.unmark);
|
||||
this.unsubscribeShare = eventBus.subscribe(EXTERNAL_EVENT.SHARE_SDOC, this.onShareToggle);
|
||||
this.unsubscribeFreezeDocument = eventBus.subscribe(EXTERNAL_EVENT.FREEZE_DOCUMENT, this.onFreezeDocument);
|
||||
this.unsubscribeUnfreeze = eventBus.subscribe(EXTERNAL_EVENT.UNFREEZE, this.unFreeze);
|
||||
@@ -67,16 +65,6 @@ class ExternalOperations extends React.Component {
|
||||
this.setState({ isShowInternalLinkDialog: !this.state.isShowInternalLinkDialog });
|
||||
};
|
||||
|
||||
unmark = () => {
|
||||
const { repoID, docPath } = this.props;
|
||||
seafileAPI.sdocUnmarkAsDraft(repoID, docPath).then((res) => {
|
||||
this.props.unmarkDraft();
|
||||
}).catch(error => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
};
|
||||
|
||||
toggleStar = () => {
|
||||
const { isStarred, repoID, docPath } = this.props;
|
||||
if (isStarred) {
|
||||
@@ -147,9 +135,9 @@ class ExternalOperations extends React.Component {
|
||||
return isDuplicated;
|
||||
};
|
||||
|
||||
onAddFile = (filePath, isMarkdownDraft) => {
|
||||
onAddFile = (filePath) => {
|
||||
let repoID = this.props.repoID;
|
||||
seafileAPI.createFile(repoID, filePath, isMarkdownDraft).then((res) => {
|
||||
seafileAPI.createFile(repoID, filePath).then((res) => {
|
||||
const eventBus = EventBus.getInstance();
|
||||
eventBus.dispatch(EXTERNAL_EVENT.INSERT_LINK, { data: res.data });
|
||||
}).catch((error) => {
|
||||
|
@@ -26,10 +26,6 @@ export default class SdocEditor extends React.Component {
|
||||
this.setState({ isStarred: isStarred });
|
||||
};
|
||||
|
||||
unmarkDraft = () => {
|
||||
this.setState({ isDraft: false });
|
||||
};
|
||||
|
||||
onSetFavicon = (suffix) => {
|
||||
let { docName } = window.seafile;
|
||||
if (suffix) {
|
||||
@@ -89,7 +85,6 @@ export default class SdocEditor extends React.Component {
|
||||
direntList={direntList}
|
||||
dirPath={dirPath}
|
||||
toggleStar={this.toggleStar}
|
||||
unmarkDraft={this.unmarkDraft}
|
||||
onNewNotification={this.onNewNotification}
|
||||
onClearNotification={this.onClearNotification}
|
||||
/>
|
||||
|
@@ -131,21 +131,6 @@ export const useNewAPI = window.fileHistory ? window.fileHistory.pageOptions.use
|
||||
export const canDownload = window.fileHistory ? window.fileHistory.pageOptions.can_download_file : '';
|
||||
export const canCompare = window.fileHistory ? window.fileHistory.pageOptions.can_compare : '';
|
||||
|
||||
// Draft review
|
||||
export const draftFilePath = window.draft ? window.draft.config.draftFilePath: '';
|
||||
export const draftOriginFilePath = window.draft ? window.draft.config.draftOriginFilePath: '';
|
||||
export const draftFileName = window.draft ? window.draft.config.draftFileName: '';
|
||||
export const draftID = window.draft ? window.draft.config.draftID : '';
|
||||
export const draftRepoID = window.draft ? window.draft.config.draftRepoID : '';
|
||||
export const author = window.draft ? window.draft.config.author : '';
|
||||
export const authorAvatar = window.draft ? window.draft.config.authorAvatar : '';
|
||||
export const originFileExists = window.draft ? window.draft.config.originFileExists : '';
|
||||
export const draftFileExists = window.draft ? window.draft.config.draftFileExists : '';
|
||||
export const draftStatus = window.draft ? window.draft.config.draftStatus : '';
|
||||
export const draftPublishVersion = window.draft ? window.draft.config.draftPublishVersion : '';
|
||||
export const originFileVersion = window.draft ? window.draft.config.originFileVersion : '';
|
||||
export const filePermission = window.draft ? window.draft.config.perm : '';
|
||||
|
||||
// org admin
|
||||
export const orgID = window.org ? window.org.pageOptions.orgID : '';
|
||||
export const orgName = window.org ? window.org.pageOptions.orgName : '';
|
||||
|
@@ -38,10 +38,6 @@ class EditorUtilities {
|
||||
});
|
||||
}
|
||||
|
||||
createFile(filePath, isDraft) {
|
||||
return seafileAPI.createFile(repoID, filePath, isDraft);
|
||||
}
|
||||
|
||||
deleteFile(filePath) {
|
||||
return seafileAPI.deleteFile(repoID, filePath);
|
||||
}
|
||||
@@ -95,18 +91,6 @@ class EditorUtilities {
|
||||
return seafileAPI.revertFile(historyRepoID, filePath, commitID);
|
||||
}
|
||||
|
||||
listDrafts() {
|
||||
return seafileAPI.listDrafts();
|
||||
}
|
||||
|
||||
deleteDraft(id) {
|
||||
return seafileAPI.deleteDraft(id);
|
||||
}
|
||||
|
||||
publishDraft(id) {
|
||||
return seafileAPI.publishDraft(id);
|
||||
}
|
||||
|
||||
zipDownload(parent_dir, dirents) {
|
||||
return seafileAPI.zipDownload(repoID, parent_dir, dirents);
|
||||
}
|
||||
|
@@ -27,8 +27,6 @@ const TextTranslation = {
|
||||
'CONVERT_TO_SDOC' : {key : 'Convert to sdoc', value : gettext('Convert to sdoc')},
|
||||
'CONVERT_TO_DOCX' : {key : 'Convert to docx', value : gettext('Convert to docx')},
|
||||
'EXPORT_DOCX' : {key : 'Export docx', value : gettext('Export as docx')},
|
||||
'MARK_AS_DRAFT' : {key : 'Mark as draft', value : gettext('Mark as draft')},
|
||||
'UNMARK_AS_DRAFT' : {key : 'Unmark as draft', value : gettext('Unmark as draft')},
|
||||
'HISTORY' : {key : 'History', value : gettext('History')},
|
||||
'ACCESS_LOG' : {key : 'Access Log', value : gettext('Access Log')},
|
||||
'PROPERTIES' : {key : 'Properties', value : gettext('Properties')},
|
||||
|
@@ -20,9 +20,6 @@ class URLDecorator {
|
||||
case 'open_via_client':
|
||||
url = 'seafile://openfile?repo_id=' + options.repoID + '&path=' + Utils.encodePath(options.filePath);
|
||||
break;
|
||||
case 'draft_view':
|
||||
url = siteRoot + 'lib/' + options.repoID + '/file' + options.filePath + '?mode=edit&draft_id=' + options.draftId;
|
||||
break;
|
||||
default:
|
||||
url = '';
|
||||
break;
|
||||
|
@@ -620,15 +620,6 @@ export const Utils = {
|
||||
}
|
||||
|
||||
if (permission == 'rw') {
|
||||
/*
|
||||
if (Utils.isSdocFile(dirent.name)) {
|
||||
if (dirent.is_sdoc_draft) {
|
||||
list.push(UNMARK_AS_DRAFT);
|
||||
} else {
|
||||
list.push(MARK_AS_DRAFT);
|
||||
}
|
||||
}
|
||||
*/
|
||||
list.push('Divider');
|
||||
list.push(PROPERTIES, HISTORY);
|
||||
if (isPro && fileAuditEnabled) {
|
||||
|
Reference in New Issue
Block a user