|
|
@@ -1,8 +1,6 @@
|
|
|
import React, { Fragment } from 'react';
|
|
|
import PropTypes from 'prop-types';
|
|
|
|
|
|
-import Popover from 'react-bootstrap/lib/Popover';
|
|
|
-import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger';
|
|
|
import { withTranslation } from 'react-i18next';
|
|
|
|
|
|
import GrowiRenderer from '../../util/GrowiRenderer';
|
|
|
@@ -16,74 +14,46 @@ class Draft extends React.Component {
|
|
|
|
|
|
this.state = {
|
|
|
html: '',
|
|
|
+ isOpen: false,
|
|
|
};
|
|
|
|
|
|
this.growiRenderer = new GrowiRenderer(this.props.crowi, this.props.crowiOriginRenderer, { mode: 'draft' });
|
|
|
|
|
|
this.renderHtml = this.renderHtml.bind(this);
|
|
|
- this.renderButton = this.renderButton.bind(this);
|
|
|
- this.renderPopover = this.renderPopover.bind(this);
|
|
|
+ this.toggleContent = this.toggleContent.bind(this);
|
|
|
this.copyMarkdownToClipboard = this.copyMarkdownToClipboard.bind(this);
|
|
|
- }
|
|
|
-
|
|
|
- async componentDidMount() {
|
|
|
- this.setState({ html: await this.renderHtml(this.props.markdown) });
|
|
|
- }
|
|
|
-
|
|
|
- renderButton(isExist, markdown) {
|
|
|
- if (isExist) {
|
|
|
- return (
|
|
|
- <a
|
|
|
- className="draft-copy"
|
|
|
- data-toggle="tooltip"
|
|
|
- data-placement="bottom"
|
|
|
- title={this.props.t('Copy')}
|
|
|
- onClick={this.copyMarkdownToClipboard}
|
|
|
- >
|
|
|
- <i className="icon-doc" />
|
|
|
- </a>
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- return (
|
|
|
- <Fragment>
|
|
|
- <span className="label-draft label label-default">draft</span>
|
|
|
- <a
|
|
|
- href={`${this.props.path}#edit`}
|
|
|
- target="_blank"
|
|
|
- rel="noopener noreferrer"
|
|
|
- className="draft-delete"
|
|
|
- data-toggle="tooltip"
|
|
|
- data-placement="bottom"
|
|
|
- title={this.props.t('Edit')}
|
|
|
- onClick={() => { return this.props.clearDraft(this.props.path) }}
|
|
|
- >
|
|
|
- <i className="icon-note" />
|
|
|
- </a>
|
|
|
- </Fragment>
|
|
|
- );
|
|
|
+ this.renderAccordionTitle = this.renderAccordionTitle.bind(this);
|
|
|
}
|
|
|
|
|
|
copyMarkdownToClipboard() {
|
|
|
navigator.clipboard.writeText(this.props.markdown);
|
|
|
}
|
|
|
|
|
|
- renderPopover(id, markdown) {
|
|
|
- return (
|
|
|
- <Popover id={id}>
|
|
|
- <RevisionBody html={this.state.html} />
|
|
|
- </Popover>
|
|
|
- );
|
|
|
+ async toggleContent(e) {
|
|
|
+ const target = e.currentTarget.getAttribute('data-target');
|
|
|
+
|
|
|
+ if (!this.state.html) {
|
|
|
+ await this.renderHtml();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.state.isOpen) {
|
|
|
+ $(target).collapse('hide');
|
|
|
+ this.setState({ isOpen: false });
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ $(target).collapse('show');
|
|
|
+ this.setState({ isOpen: true });
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- async renderHtml(markdown) {
|
|
|
+ async renderHtml() {
|
|
|
const context = {
|
|
|
- markdown,
|
|
|
+ markdown: this.props.markdown,
|
|
|
};
|
|
|
|
|
|
const growiRenderer = this.growiRenderer;
|
|
|
const interceptorManager = this.props.crowi.interceptorManager;
|
|
|
- const html = await interceptorManager.process('prePreProcess', context)
|
|
|
+ await interceptorManager.process('prePreProcess', context)
|
|
|
.then(() => {
|
|
|
context.markdown = growiRenderer.preProcess(context.markdown);
|
|
|
})
|
|
|
@@ -97,38 +67,86 @@ class Draft extends React.Component {
|
|
|
context.parsedHTML = growiRenderer.postProcess(context.parsedHTML);
|
|
|
})
|
|
|
.then(() => { return interceptorManager.process('postPostProcess', context) })
|
|
|
- .then(() => { return context.parsedHTML });
|
|
|
+ .then(() => {
|
|
|
+ this.setState({ html: context.parsedHTML });
|
|
|
+ });
|
|
|
+ }
|
|
|
|
|
|
- return html;
|
|
|
+ renderAccordionTitle(isExist) {
|
|
|
+ if (isExist) {
|
|
|
+ return (
|
|
|
+ <Fragment>
|
|
|
+ <span>{this.props.path}</span>
|
|
|
+ <span className="mx-2">({this.props.t('page exists')})</span>
|
|
|
+ </Fragment>
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ return (
|
|
|
+ <Fragment>
|
|
|
+ <a href={`${this.props.path}#edit`} target="_blank" rel="noopener noreferrer">{this.props.path}</a>
|
|
|
+ <span className="mx-2">
|
|
|
+ <span className="label-draft label label-default">draft</span>
|
|
|
+ </span>
|
|
|
+ </Fragment>
|
|
|
+ );
|
|
|
}
|
|
|
|
|
|
render() {
|
|
|
const { t } = this.props;
|
|
|
+ const id = this.props.path.replace('/', '-');
|
|
|
|
|
|
return (
|
|
|
- <li className="d-flex align-items-center">
|
|
|
- <OverlayTrigger placement="bottom" overlay={this.renderPopover(this.props.path, this.props.markdown)}>
|
|
|
- <span
|
|
|
- data-toggle="tooltip"
|
|
|
- data-placement="bottom"
|
|
|
- title={t('Click to copy')}
|
|
|
- onClick={this.copyMarkdownToClipboard}
|
|
|
- >
|
|
|
- <i className="icon-doc"></i>
|
|
|
- {this.props.path} {this.props.isExist ? `(${t('page exists')})` : ''}
|
|
|
- </span>
|
|
|
- </OverlayTrigger>
|
|
|
- {this.renderButton(this.props.isExist, this.props.markdown)}
|
|
|
- <a
|
|
|
- className="text-danger draft-delete"
|
|
|
- data-toggle="tooltip"
|
|
|
- data-placement="top"
|
|
|
- title={t('Delete')}
|
|
|
- onClick={() => { return this.props.clearDraft(this.props.path) }}
|
|
|
- >
|
|
|
- <i className="icon-trash" />
|
|
|
- </a>
|
|
|
- </li>
|
|
|
+ <div className="timeline-body">
|
|
|
+ <div className="panel panel-timeline">
|
|
|
+ <div className="panel-heading d-flex justify-content-between">
|
|
|
+ <div className="panel-title" onClick={this.toggleContent} data-target={`#${id}`}>
|
|
|
+ {this.renderAccordionTitle(this.props.isExist)}
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ {this.props.isExist
|
|
|
+ ? null
|
|
|
+ : (
|
|
|
+ <a
|
|
|
+ href={`${this.props.path}#edit`}
|
|
|
+ target="_blank"
|
|
|
+ rel="noopener noreferrer"
|
|
|
+ className="draft-edit"
|
|
|
+ data-toggle="tooltip"
|
|
|
+ data-placement="bottom"
|
|
|
+ title={this.props.t('Edit')}
|
|
|
+ >
|
|
|
+ <i className="icon-note" />
|
|
|
+ </a>
|
|
|
+ )
|
|
|
+ }
|
|
|
+ <a
|
|
|
+ className="draft-copy"
|
|
|
+ data-toggle="tooltip"
|
|
|
+ data-placement="bottom"
|
|
|
+ title={this.props.t('Copy')}
|
|
|
+ onClick={this.copyMarkdownToClipboard}
|
|
|
+ >
|
|
|
+ <i className="icon-doc" />
|
|
|
+ </a>
|
|
|
+ <a
|
|
|
+ className="text-danger draft-delete"
|
|
|
+ data-toggle="tooltip"
|
|
|
+ data-placement="top"
|
|
|
+ title={t('Delete')}
|
|
|
+ onClick={() => { return this.props.clearDraft(this.props.path) }}
|
|
|
+ >
|
|
|
+ <i className="icon-trash" />
|
|
|
+ </a>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className="panel-body collapse" id={id} aria-labelledby={id} data-parent="#draft-list">
|
|
|
+ <div className="revision-body wiki">
|
|
|
+ <RevisionBody html={this.state.html} />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
);
|
|
|
}
|
|
|
|