PageAttachment.jsx 4.9 KB

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