actions.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. import moment from 'moment';
  2. import * as post from 'misago/reducers/post';
  3. import * as posts from 'misago/reducers/posts';
  4. import ajax from 'misago/services/ajax';
  5. import snackbar from 'misago/services/snackbar';
  6. import store from 'misago/services/store';
  7. export function approve(props) {
  8. props.selection.forEach((selection) => {
  9. store.dispatch(post.patch(selection, {
  10. is_unapproved: false
  11. }));
  12. const ops = [
  13. {'op': 'replace', 'path': 'is-unapproved', 'value': false}
  14. ];
  15. const previousState = {
  16. is_unapproved: selection.is_unapproved
  17. };
  18. patch(selection, ops, previousState);
  19. });
  20. store.dispatch(posts.deselectAll());
  21. }
  22. export function protect(props) {
  23. props.selection.forEach((selection) => {
  24. store.dispatch(post.patch(selection, {
  25. is_protected: false
  26. }));
  27. const ops = [
  28. {'op': 'replace', 'path': 'is-protected', 'value': true}
  29. ];
  30. const previousState = {
  31. is_protected: selection.is_protected
  32. };
  33. patch(selection, ops, previousState);
  34. });
  35. store.dispatch(posts.deselectAll());
  36. }
  37. export function unprotect(props) {
  38. props.selection.forEach((selection) => {
  39. store.dispatch(post.patch(selection, {
  40. is_protected: false
  41. }));
  42. const ops = [
  43. {'op': 'replace', 'path': 'is-protected', 'value': false}
  44. ];
  45. const previousState = {
  46. is_protected: selection.is_protected
  47. };
  48. patch(selection, ops, previousState);
  49. });
  50. store.dispatch(posts.deselectAll());
  51. }
  52. export function hide(props) {
  53. props.selection.forEach((selection) => {
  54. store.dispatch(post.patch(selection, {
  55. is_hidden: true,
  56. hidden_on: moment(),
  57. hidden_by_name: props.user.username,
  58. url: Object.assign(selection.url, {
  59. hidden_by: props.user.url
  60. })
  61. }));
  62. const ops = [
  63. {'op': 'replace', 'path': 'is-hidden', 'value': true}
  64. ];
  65. const previousState = {
  66. is_hidden: selection.is_hidden,
  67. hidden_on: selection.hidden_on,
  68. hidden_by_name: selection.hidden_by_name,
  69. url: selection.url
  70. };
  71. patch(selection, ops, previousState);
  72. });
  73. store.dispatch(posts.deselectAll());
  74. }
  75. export function unhide(props) {
  76. props.selection.forEach((selection) => {
  77. store.dispatch(post.patch(selection, {
  78. is_hidden: false
  79. }));
  80. const ops = [
  81. {'op': 'replace', 'path': 'is-hidden', 'value': false}
  82. ];
  83. const previousState = {
  84. is_hidden: selection.is_hidden
  85. };
  86. patch(selection, ops, previousState);
  87. });
  88. store.dispatch(posts.deselectAll());
  89. }
  90. export function patch(selection, ops, previousState) {
  91. ajax.patch(selection.api.index, ops).then((newState) => {
  92. store.dispatch(post.patch(selection, newState));
  93. }, (rejection) => {
  94. if (rejection.status === 400) {
  95. snackbar.error(rejection.detail[0]);
  96. } else {
  97. snackbar.apiError(rejection);
  98. }
  99. store.dispatch(post.patch(selection, previousState));
  100. });
  101. }
  102. export function merge(props) {
  103. let confirmed = confirm(gettext("Are you sure you want to merge selected posts? This action is not reversible!"));
  104. if (!confirmed) {
  105. return;
  106. }
  107. props.selection.slice(1).map((selection) => {
  108. store.dispatch(post.patch(selection, {
  109. isDeleted: true
  110. }));
  111. });
  112. ajax.post(props.thread.api.posts.merge, {
  113. posts: props.selection.map((post) => post.id)
  114. }).then((data) => {
  115. store.dispatch(post.patch(data, post.hydrate(data)));
  116. }, (rejection) => {
  117. if (rejection.status === 400) {
  118. snackbar.error(rejection.detail);
  119. } else {
  120. snackbar.apiError(rejection);
  121. }
  122. props.selection.slice(1).map((selection) => {
  123. store.dispatch(post.patch(selection, {
  124. isDeleted: false
  125. }));
  126. });
  127. });
  128. store.dispatch(posts.deselectAll());
  129. }
  130. export function remove(props) {
  131. let confirmed = confirm(gettext("Are you sure you want to delete selected posts? This action is not reversible!"));
  132. if (!confirmed) {
  133. return;
  134. }
  135. props.selection.map((selection) => {
  136. store.dispatch(post.patch(selection, {
  137. isDeleted: true
  138. }));
  139. });
  140. const ids = props.selection.map((post) => { return post.id; });
  141. ajax.delete(props.thread.api.posts.index, ids).then(() => {
  142. return;
  143. }, (rejection) => {
  144. if (rejection.status === 400) {
  145. snackbar.error(rejection.detail);
  146. } else {
  147. snackbar.apiError(rejection);
  148. }
  149. props.selection.map((selection) => {
  150. store.dispatch(post.patch(selection, {
  151. isDeleted: false
  152. }));
  153. });
  154. });
  155. store.dispatch(posts.deselectAll());
  156. }