PageAttachment.jsx 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /* eslint-disable react/no-access-state-in-setstate */
  2. import React from 'react';
  3. import PropTypes from 'prop-types';
  4. import { withTranslation } from 'react-i18next';
  5. import PageAttachmentList from './PageAttachment/PageAttachmentList';
  6. import DeleteAttachmentModal from './PageAttachment/DeleteAttachmentModal';
  7. import PaginationWrapper from './PaginationWrapper';
  8. import { withUnstatedContainers } from './UnstatedUtils';
  9. import AppContainer from '../services/AppContainer';
  10. import PageContainer from '../services/PageContainer';
  11. class PageAttachment extends React.Component {
  12. constructor(props) {
  13. super(props);
  14. this.state = {
  15. activePage: 1,
  16. limit: 10,
  17. totalAttachments: 0,
  18. attachments: [],
  19. inUse: {},
  20. attachmentToDelete: null,
  21. deleting: false,
  22. deleteError: '',
  23. };
  24. this.handlePage = this.handlePage.bind(this);
  25. this.onAttachmentDeleteClicked = this.onAttachmentDeleteClicked.bind(this);
  26. this.onAttachmentDeleteClickedConfirm = this.onAttachmentDeleteClickedConfirm.bind(this);
  27. }
  28. async handlePage(selectedPage) {
  29. const { pageId } = this.props.pageContainer.state;
  30. const { limit } = this.state;
  31. const offset = (selectedPage - 1) * limit;
  32. const activePage = selectedPage;
  33. if (!pageId) { return }
  34. const res = await this.props.appContainer.apiv3Get('/attachment/list', {
  35. pageId, limit, offset,
  36. });
  37. const attachments = res.data.paginateResult.docs;
  38. const totalAttachments = res.data.paginateResult.totalDocs;
  39. const inUse = {};
  40. for (const attachment of attachments) {
  41. inUse[attachment._id] = this.checkIfFileInUse(attachment);
  42. }
  43. this.setState({
  44. activePage,
  45. totalAttachments,
  46. attachments,
  47. inUse,
  48. });
  49. }
  50. async componentDidMount() {
  51. await this.handlePage(1);
  52. }
  53. checkIfFileInUse(attachment) {
  54. const { markdown } = this.props.pageContainer.state;
  55. if (markdown.match(attachment._id)) {
  56. return true;
  57. }
  58. return false;
  59. }
  60. onAttachmentDeleteClicked(attachment) {
  61. this.setState({
  62. attachmentToDelete: attachment,
  63. });
  64. }
  65. onAttachmentDeleteClickedConfirm(attachment) {
  66. const attachmentId = attachment._id;
  67. this.setState({
  68. deleting: true,
  69. });
  70. this.props.appContainer.apiPost('/attachments.remove', { attachment_id: attachmentId })
  71. .then((res) => {
  72. this.setState({
  73. attachments: this.state.attachments.filter((at) => {
  74. // comparing ObjectId
  75. // eslint-disable-next-line eqeqeq
  76. return at._id != attachmentId;
  77. }),
  78. attachmentToDelete: null,
  79. deleting: false,
  80. });
  81. }).catch((err) => {
  82. this.setState({
  83. deleteError: 'Something went wrong.',
  84. deleting: false,
  85. });
  86. });
  87. }
  88. isUserLoggedIn() {
  89. return this.props.appContainer.currentUser != null;
  90. }
  91. render() {
  92. const { t } = this.props;
  93. if (this.state.attachments.length === 0) {
  94. return t('No attachments yet.');
  95. }
  96. let deleteAttachmentModal = '';
  97. if (this.isUserLoggedIn()) {
  98. const attachmentToDelete = this.state.attachmentToDelete;
  99. const deleteModalClose = () => {
  100. this.setState({ attachmentToDelete: null, deleteError: '' });
  101. };
  102. const showModal = attachmentToDelete !== null;
  103. let deleteInUse = null;
  104. if (attachmentToDelete !== null) {
  105. deleteInUse = this.state.inUse[attachmentToDelete._id] || false;
  106. }
  107. deleteAttachmentModal = (
  108. <DeleteAttachmentModal
  109. isOpen={showModal}
  110. animation={false}
  111. toggle={deleteModalClose}
  112. attachmentToDelete={attachmentToDelete}
  113. inUse={deleteInUse}
  114. deleting={this.state.deleting}
  115. deleteError={this.state.deleteError}
  116. onAttachmentDeleteClickedConfirm={this.onAttachmentDeleteClickedConfirm}
  117. />
  118. );
  119. }
  120. return (
  121. <div>
  122. <PageAttachmentList
  123. attachments={this.state.attachments}
  124. inUse={this.state.inUse}
  125. onAttachmentDeleteClicked={this.onAttachmentDeleteClicked}
  126. isUserLoggedIn={this.isUserLoggedIn()}
  127. />
  128. {deleteAttachmentModal}
  129. <PaginationWrapper
  130. activePage={this.state.activePage}
  131. changePage={this.handlePage}
  132. totalItemsCount={this.state.totalAttachments}
  133. pagingLimit={this.state.limit}
  134. />
  135. </div>
  136. );
  137. }
  138. }
  139. /**
  140. * Wrapper component for using unstated
  141. */
  142. const PageAttachmentWrapper = withUnstatedContainers(PageAttachment, [AppContainer, PageContainer]);
  143. PageAttachment.propTypes = {
  144. t: PropTypes.func.isRequired,
  145. appContainer: PropTypes.instanceOf(AppContainer).isRequired,
  146. pageContainer: PropTypes.instanceOf(PageContainer).isRequired,
  147. };
  148. export default withTranslation()(PageAttachmentWrapper);