|
|
@@ -1,16 +1,16 @@
|
|
|
-import React from 'react';
|
|
|
+import React, { Suspense } from 'react';
|
|
|
import PropTypes from 'prop-types';
|
|
|
import { withTranslation } from 'react-i18next';
|
|
|
|
|
|
-import * as toastr from 'toastr';
|
|
|
+import { toastSuccess, toastError } from '../../util/apiNotification';
|
|
|
|
|
|
import { withUnstatedContainers } from '../UnstatedUtils';
|
|
|
import AppContainer from '../../services/AppContainer';
|
|
|
-import NavigationContainer from '../../services/NavigationContainer';
|
|
|
import PageContainer from '../../services/PageContainer';
|
|
|
import EditorContainer from '../../services/EditorContainer';
|
|
|
|
|
|
-import TagEditor from './TagEditor';
|
|
|
+import RenderTagLabels from './RenderTagLabels';
|
|
|
+import TagEditModal from './TagEditModal';
|
|
|
|
|
|
class TagLabels extends React.Component {
|
|
|
|
|
|
@@ -18,118 +18,83 @@ class TagLabels extends React.Component {
|
|
|
super(props);
|
|
|
|
|
|
this.state = {
|
|
|
- showTagEditor: false,
|
|
|
+ isTagEditModalShown: false,
|
|
|
};
|
|
|
|
|
|
- this.showEditor = this.showEditor.bind(this);
|
|
|
+ this.openEditorModal = this.openEditorModal.bind(this);
|
|
|
+ this.closeEditorModal = this.closeEditorModal.bind(this);
|
|
|
this.tagsUpdatedHandler = this.tagsUpdatedHandler.bind(this);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @return tags data
|
|
|
- * 1. pageContainer.state.tags if editorMode is null
|
|
|
- * 2. editorContainer.state.tags if editorMode is not null
|
|
|
+ * 1. pageContainer.state.tags if isEditorMode is false
|
|
|
+ * 2. editorContainer.state.tags if isEditorMode is true
|
|
|
*/
|
|
|
getEditTargetData() {
|
|
|
- const { editorMode } = this.props.navigationContainer.state;
|
|
|
- return (editorMode == null)
|
|
|
- ? this.props.pageContainer.state.tags
|
|
|
- : this.props.editorContainer.state.tags;
|
|
|
+ const { isEditorMode } = this.props;
|
|
|
+ return (isEditorMode) ? this.props.editorContainer.state.tags : this.props.pageContainer.state.tags;
|
|
|
}
|
|
|
|
|
|
- showEditor() {
|
|
|
- this.tagEditor.show(this.getEditTargetData());
|
|
|
+ openEditorModal() {
|
|
|
+ this.setState({ isTagEditModalShown: true });
|
|
|
+ }
|
|
|
+
|
|
|
+ closeEditorModal() {
|
|
|
+ this.setState({ isTagEditModalShown: false });
|
|
|
}
|
|
|
|
|
|
async tagsUpdatedHandler(tags) {
|
|
|
- const { appContainer, navigationContainer, editorContainer } = this.props;
|
|
|
- const { editorMode } = navigationContainer.state;
|
|
|
+ const { appContainer, editorContainer, isEditorMode } = this.props;
|
|
|
|
|
|
- // post api request and update tags
|
|
|
- if (editorMode == null) {
|
|
|
- const { pageContainer } = this.props;
|
|
|
-
|
|
|
- try {
|
|
|
- const { pageId } = pageContainer.state;
|
|
|
- await appContainer.apiPost('/tags.update', { pageId, tags });
|
|
|
-
|
|
|
- // update pageContainer.state
|
|
|
- pageContainer.setState({ tags });
|
|
|
- editorContainer.setState({ tags });
|
|
|
-
|
|
|
- this.apiSuccessHandler();
|
|
|
- }
|
|
|
- catch (err) {
|
|
|
- this.apiErrorHandler(err);
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
// only update tags in editorContainer
|
|
|
- else {
|
|
|
- editorContainer.setState({ tags });
|
|
|
+ if (isEditorMode) {
|
|
|
+ return editorContainer.setState({ tags });
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- apiSuccessHandler() {
|
|
|
- toastr.success(undefined, 'updated tags successfully', {
|
|
|
- closeButton: true,
|
|
|
- progressBar: true,
|
|
|
- newestOnTop: false,
|
|
|
- showDuration: '100',
|
|
|
- hideDuration: '100',
|
|
|
- timeOut: '1200',
|
|
|
- extendedTimeOut: '150',
|
|
|
- });
|
|
|
- }
|
|
|
+ // post api request and update tags
|
|
|
+ const { pageContainer } = this.props;
|
|
|
+
|
|
|
+ try {
|
|
|
+ const { pageId } = pageContainer.state;
|
|
|
+ await appContainer.apiPost('/tags.update', { pageId, tags });
|
|
|
+
|
|
|
+ // update pageContainer.state
|
|
|
+ pageContainer.setState({ tags });
|
|
|
+ editorContainer.setState({ tags });
|
|
|
|
|
|
- apiErrorHandler(err) {
|
|
|
- toastr.error(err.message, 'Error occured', {
|
|
|
- closeButton: true,
|
|
|
- progressBar: true,
|
|
|
- newestOnTop: false,
|
|
|
- showDuration: '100',
|
|
|
- hideDuration: '100',
|
|
|
- timeOut: '3000',
|
|
|
- });
|
|
|
+ toastSuccess('updated tags successfully');
|
|
|
+ }
|
|
|
+ catch (err) {
|
|
|
+ toastError(err, 'fail to update tags');
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- render() {
|
|
|
- const { t } = this.props;
|
|
|
- const { pageId } = this.props.pageContainer.state;
|
|
|
|
|
|
+ render() {
|
|
|
const tags = this.getEditTargetData();
|
|
|
|
|
|
- const tagElements = tags.map((tag) => {
|
|
|
- return (
|
|
|
- <span key={`${pageId}_${tag}`} className="text-muted">
|
|
|
- <i className="tag-icon icon-tag mr-1"></i>
|
|
|
- <a className="tag-name mr-2" href={`/_search?q=tag:${tag}`} key={`${pageId}_${tag}_link`}>{tag}</a>
|
|
|
- </span>
|
|
|
- );
|
|
|
- });
|
|
|
-
|
|
|
return (
|
|
|
- <div className="tag-labels">
|
|
|
- {tags.length === 0 && (
|
|
|
- <a className="btn btn-link btn-edit-tags no-tags p-0 text-muted" onClick={this.showEditor}>
|
|
|
- { t('Add tags for this page') } <i className="manage-tags ml-2 icon-plus"></i>
|
|
|
- </a>
|
|
|
- )}
|
|
|
- {tagElements}
|
|
|
- {tags.length > 0 && (
|
|
|
- <a className="btn btn-link btn-edit-tags p-0 text-muted" onClick={this.showEditor}>
|
|
|
- <i className="manage-tags ml-2 icon-plus"></i> { t('Edit tags for this page') }
|
|
|
- </a>
|
|
|
- )}
|
|
|
-
|
|
|
- <TagEditor
|
|
|
- ref={(c) => { this.tagEditor = c }}
|
|
|
+ <React.Fragment>
|
|
|
+
|
|
|
+ <div className="tag-labels">
|
|
|
+ <Suspense fallback={<p>...</p>}>
|
|
|
+ <RenderTagLabels
|
|
|
+ tags={tags}
|
|
|
+ openEditorModal={this.openEditorModal}
|
|
|
+ />
|
|
|
+ </Suspense>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <TagEditModal
|
|
|
+ tags={tags}
|
|
|
+ isOpen={this.state.isTagEditModalShown}
|
|
|
+ onClose={this.closeEditorModal}
|
|
|
appContainer={this.props.appContainer}
|
|
|
- show={this.state.showTagEditor}
|
|
|
onTagsUpdated={this.tagsUpdatedHandler}
|
|
|
- >
|
|
|
- </TagEditor>
|
|
|
- </div>
|
|
|
+ />
|
|
|
+
|
|
|
+ </React.Fragment>
|
|
|
);
|
|
|
}
|
|
|
|
|
|
@@ -138,15 +103,20 @@ class TagLabels extends React.Component {
|
|
|
/**
|
|
|
* Wrapper component for using unstated
|
|
|
*/
|
|
|
-const TagLabelsWrapper = withUnstatedContainers(TagLabels, [AppContainer, NavigationContainer, PageContainer, EditorContainer]);
|
|
|
-
|
|
|
+const TagLabelsWrapper = withUnstatedContainers(TagLabels, [AppContainer, PageContainer, EditorContainer]);
|
|
|
|
|
|
TagLabels.propTypes = {
|
|
|
t: PropTypes.func.isRequired, // i18next
|
|
|
+
|
|
|
appContainer: PropTypes.instanceOf(AppContainer).isRequired,
|
|
|
- navigationContainer: PropTypes.instanceOf(NavigationContainer).isRequired,
|
|
|
pageContainer: PropTypes.instanceOf(PageContainer).isRequired,
|
|
|
editorContainer: PropTypes.instanceOf(EditorContainer).isRequired,
|
|
|
+
|
|
|
+ isEditorMode: PropTypes.bool,
|
|
|
+};
|
|
|
+
|
|
|
+TagLabels.defaultProps = {
|
|
|
+ isEditorMode: false,
|
|
|
};
|
|
|
|
|
|
export default withTranslation()(TagLabelsWrapper);
|