action(test).js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. import { store } from "."
  2. import { useGetState } from 'react-redux';
  3. import { useHistory } from "react-router-dom";
  4. const url = 'http://hipstagram.node.ed.asmer.org.ua/graphql'
  5. // функция getGql
  6. function getGql(endpoint) {
  7. return async function gql(query, variables = {}) {
  8. let headers = {
  9. 'Content-Type': 'application/json;charset=utf-8',
  10. 'Accept': 'application/json',
  11. }
  12. if (('authToken' in localStorage)) {
  13. headers.Authorization = 'Bearer ' + localStorage.authToken
  14. }
  15. let result = await fetch(endpoint, {
  16. method: 'POST',
  17. headers,
  18. body: JSON.stringify({
  19. query,
  20. variables
  21. })
  22. }).then(res => res.json())
  23. if (('errors' in result) && !('data' in result)) {
  24. throw new Error(JSON.stringify(result.errors))
  25. }
  26. result = Object.values(result.data)[0]
  27. return result
  28. }
  29. }
  30. const gql = getGql(url)
  31. // акшоны для promiseReducer
  32. export const actionPending = (type, nameOfPromise) => ({ nameOfPromise, type, status: 'PENDING' })
  33. export const actionFulfilled = (type, nameOfPromise, payload) => ({ nameOfPromise, type: type, status: 'FULFILLED', payload })
  34. export const actionRejected = (type, nameOfPromise, error) => ({ nameOfPromise, type: type, status: 'REJECTED', error })
  35. export const actionPromise = (type, nameOfPromise, promise) =>
  36. async dispatch => {
  37. dispatch(actionPending(type, nameOfPromise)) //сигнализируем redux, что промис начался
  38. try {
  39. const payload = await promise //ожидаем промиса
  40. dispatch(actionFulfilled(type, nameOfPromise, payload)) //сигнализируем redux, что промис успешно выполнен
  41. return payload //в месте запуска store.dispatch с этим thunk можно так же получить результат промиса
  42. }
  43. catch (error) {
  44. dispatch(actionRejected(type, nameOfPromise, error)) //в случае ошибки - сигнализируем redux, что промис несложился
  45. }
  46. }
  47. // =============================================================
  48. // Запросы на бек
  49. // Запрос на регистрацию пользователя
  50. export const actionRegistration = (login, password) => actionPromise('PROMISE', 'Registration', gql(`mutation Registration($login:String!, $password:String!) {
  51. createUser(login:$login, password:$password) {
  52. _id login
  53. }
  54. }`, {
  55. login,
  56. password
  57. })
  58. )
  59. // Запрос на логинизацию пользователя
  60. export const actionLogin = (login, password) => actionPromise('PROMISE', 'Login', gql(`query Login($login: String!, $password: String!) {
  61. login(login: $login, password: $password)
  62. }`, {
  63. login,
  64. password
  65. }))
  66. // акшон для логинизации в authReduser
  67. const actionAuthLogin = token => ({ type: 'AUTH_LOGIN', token })
  68. // акшон для раззлогинивания
  69. export const actionAuthLogout = () => ({ type: 'AUTH_LOGOUT' })
  70. // запрос на изменение пароля юзера
  71. export const actionPassChange = (loginChange, passwordChange, passwordNew) => actionPromise('PROMISE', 'PassChange', gql(`mutation PasswordChange($loginChange: String!, $passwordChange: String!, $passwordNew: String!) {
  72. changePassword(
  73. login: $loginChange, password: $passwordChange, newPassword: $passwordNew
  74. ) {
  75. _id login
  76. }
  77. }`, {
  78. loginChange,
  79. passwordChange,
  80. passwordNew
  81. }))
  82. // запрос на поиск конкретного поста
  83. export const actionFindPostOne = _id => actionPromise('PROMISE', 'PostFindOne', gql(`query OnePostFind ($postOne: String){
  84. PostFindOne (query: $postOne) {
  85. _id createdAt title text likesCount
  86. images {
  87. url
  88. }
  89. comments {
  90. _id createdAt text answers {
  91. _id createdAt text likes {
  92. _id
  93. }
  94. likesCount owner {
  95. _id login nick avatar {
  96. _id url
  97. }
  98. }
  99. }
  100. likesCount
  101. }
  102. owner {
  103. _id login nick avatar {
  104. _id url
  105. }
  106. }
  107. }
  108. }`, {
  109. postOne: JSON.stringify([{ _id }])
  110. }))
  111. // запрос на поиск конкретного юзера(folowwing - это те, на кого я подписан. followers - те, кто на меня подписан)
  112. // export const actionFindUserOne = (_id, promiseName = 'UserFindOne') => actionPromise('PROMISE', promiseName, gql(`query OneUserFind ($userOne: String) {
  113. // UserFindOne(query: $userOne) {
  114. // _id createdAt login nick
  115. // avatar {
  116. // _id url
  117. // }
  118. // followers {
  119. // _id login nick avatar {_id url}
  120. // }
  121. // following {
  122. // _id login nick avatar {_id url}
  123. // }
  124. // }
  125. // }`, {
  126. // userOne: JSON.stringify([{ _id }])
  127. // }))
  128. export const actionFindUserOne = (_id, promiseName = 'UserFindOne') => actionPromise('PROMISE', promiseName, gql(`query OneUserFind ($userOne: String) {
  129. UserFindOne(query: $userOne) {
  130. _id createdAt login nick
  131. avatar {
  132. _id url
  133. }
  134. followers {
  135. _id login nick avatar {_id url}
  136. }
  137. following {
  138. _id
  139. }
  140. }
  141. }`, {
  142. userOne: JSON.stringify([{ _id }])
  143. }))
  144. // запрос на поиск всех постов на беке (нигде не должен использоваться)
  145. export const actionfindPosts = () => actionPromise('PROMISE', 'PostsFind', gql(`query AllPostsFind ($allPosts: String){
  146. PostFind(query: $allPosts){
  147. _id createdAt title text likesCount
  148. images {
  149. url
  150. }
  151. owner {
  152. _id login nick
  153. }
  154. }
  155. }`, {
  156. allPosts: JSON.stringify([{}])
  157. }))
  158. // Запрос на поиск ленты постов для юзера
  159. // export const actionFeedFindOne = (arr, sortOne, limitOne, promiseName = 'Feed') => actionPromise('PROMISE', promiseName, gql(`query FeedFindOne ($feedOne: String){
  160. // PostFind(query: $feedOne){
  161. // _id createdAt title text likesCount owner{
  162. // _id login avatar{
  163. // url
  164. // }
  165. // }
  166. // comments {
  167. // _id
  168. // }
  169. // images{
  170. // url
  171. // }
  172. // }
  173. // }`, {
  174. // // вот тут прописал limit - количество постов, которые отображаются в ленте
  175. // feedOne: JSON.stringify([{ ___owner: { $in: arr } }, { sort: [{ _id: sortOne }], limit: [limitOne] }])
  176. // }))
  177. //================= вот это тоже нужно будет удалить после тестов =====================
  178. export const actionFeedFindOne = (arr, sortOne, limitOne, promiseName = 'Feed', skipOne = 0) => actionPromise('FEED', promiseName, gql(`query FeedFindOne ($feedOne: String){
  179. PostFind(query: $feedOne){
  180. _id createdAt title text likesCount owner{
  181. _id login avatar{
  182. url
  183. }
  184. }
  185. comments {
  186. _id
  187. }
  188. images{
  189. url
  190. }
  191. }
  192. }`, {
  193. // вот тут прописал limit - количество постов, которые отображаются в ленте
  194. feedOne: JSON.stringify([{ ___owner: { $in: arr } }, { sort: [{ _id: sortOne }], limit: [limitOne], skip: [skipOne] }])
  195. }))
  196. // запрос ленты с пропуском определенного количества постов.комментов
  197. // export const actionFeedFindOneSkip = (arr, sortOne, skipOne, limitOne, promiseName = 'Feed') => actionPromise('FEED', promiseName, gql(`query FeedFindOne ($feedOne: String){
  198. // PostFind(query: $feedOne){
  199. // _id createdAt title text likesCount owner{
  200. // _id login avatar{
  201. // url
  202. // }
  203. // }
  204. // comments {
  205. // _id
  206. // }
  207. // images{
  208. // url
  209. // }
  210. // }
  211. // }`, {
  212. // // вот тут прописал limit - количество постов, которые отображаются в ленте
  213. // feedOne: JSON.stringify([{ ___owner: { $in: arr } }, { sort: [{ _id: sortOne }], skip: [skipOne], limit: [limitOne] }])
  214. // }))
  215. // ====================== и это удалить после теста ====================
  216. export const actionFeedFindOneSkip = (arr, sortOne, skipOne, limitOne, promiseName = 'Feed') => actionPromise('FEED', promiseName, gql(`query FeedFindOne ($feedOne: String){
  217. PostFind(query: $feedOne){
  218. _id createdAt title text likesCount owner{
  219. _id login avatar{
  220. url
  221. }
  222. }
  223. comments {
  224. _id
  225. }
  226. images{
  227. url
  228. }
  229. }
  230. }`, {
  231. // вот тут прописал limit - количество постов, которые отображаются в ленте
  232. feedOne: JSON.stringify([{ ___owner: { $in: arr } }, { sort: [{ _id: sortOne }], skip: [skipOne], limit: [limitOne] }])
  233. }))
  234. // запрос на подсчет количества постов юзера
  235. export const actionPostsCount = (id, promiseName) => actionPromise('PROMISE', promiseName, gql(`query PostsCount ($postsCount: String){
  236. PostCount(query: $postsCount)
  237. }`, {
  238. postsCount: JSON.stringify([{ ___owner: id }])
  239. })
  240. )
  241. // =========================================
  242. // Thunk-и
  243. // Thunk логин и последующую логинизацию в authReduser
  244. export const actionFullLogin = (login, password) =>
  245. async dispatch => {
  246. const token = await dispatch(actionLogin(login, password))
  247. if (token !== null) {
  248. if (typeof (token) === 'string') {
  249. dispatch(actionAuthLogin(token))
  250. localStorage.authToken = token
  251. }
  252. }
  253. return token
  254. }
  255. // Thunk на регистрацию и последующую логинизацию
  256. export const actionFullRegistration = (login, password) =>
  257. async dispatch => {
  258. const token = await dispatch(actionRegistration(login, password))
  259. if (token !== null) {
  260. dispatch(actionFullLogin(login, password))
  261. }
  262. return token
  263. }
  264. // Thunk разлогина и последующей полной очистки localStorage
  265. export const actionFullLogout = () =>
  266. async dispatch => {
  267. await dispatch(actionAuthLogout())
  268. return {}
  269. }
  270. // Thunk для страницы юзера (диспатчим запрос на юзера и на ленту его постов)
  271. export const actionFullUserFindOne = _id =>
  272. async dispatch => {
  273. // запрашиваем информацию о пользователе
  274. await dispatch(actionFindUserOne(_id, 'UserFindOne'))
  275. // парсим счетчик, сколько постов у юзера
  276. dispatch(actionPostsCount(_id, 'UserPostsCount'))
  277. // запрашиваем список постов для юзера
  278. dispatch(actionFeedFindOne([_id], -1, 100, 'UserFeed'))
  279. }
  280. // запрос AboutMe для главной страницы (лента моих постов и мои данные)
  281. export const actionAboutMe = () =>
  282. async (dispatch, getState) => {
  283. const myId = getState()?.auth?.payload?.sub?.id
  284. // диспатчим запрос AboutMe (о себе)
  285. const userData = await dispatch(actionFindUserOne(myId, 'AboutMe'))
  286. // парсим счетчик, сколько постов у меня
  287. dispatch(actionPostsCount(myId, 'MyPostsCount'))
  288. let followingList = []
  289. // проверяем, есть ли вообще подписчики и если да, парсим их
  290. if (userData?.following) {
  291. // получаем id всех подписок
  292. followingList = (userData.following).map(user => user?._id)
  293. }
  294. // запрашиваем формирование ленты моих постов (первый параметр - список id, второй - это сортировка постов от новых)
  295. dispatch(actionFeedFindOne(followingList, -1, 10, 'MyFeed'))
  296. }
  297. // ================= на удаление (начало)=====================
  298. export const actionDownloadFeed = (skip) =>
  299. async (dispatch, getState) => {
  300. console.log('скипаем: ', skip)
  301. const followingList = (getState()?.promise?.AboutMe?.payload?.following).map(user => user._id)
  302. if (followingList) {
  303. const result = await dispatch(actionFeedFindOne(followingList, -1, 10, 'AddFeed', skip))
  304. return result
  305. }
  306. }
  307. // ================= на удаление(конец) =====================
  308. // запрос на загрузку картинок на бек
  309. function fileUpload(file) {
  310. const formData = new FormData()
  311. formData.append('photo', file)
  312. return (
  313. fetch('http://hipstagram.node.ed.asmer.org.ua/upload', {
  314. method: 'POST',
  315. headers: {
  316. Authorization: 'Bearer ' + localStorage.authToken
  317. },
  318. body: formData
  319. }).then(res => res.json())
  320. )
  321. }
  322. function filesUpload(files) {
  323. return Promise.all(files.map(fileUpload))
  324. }
  325. export const actionFilesUpload = (files) => actionPromise('PROMISE', 'FilesUpload',
  326. filesUpload(files)
  327. )
  328. // запрос на создание поста
  329. export const actionCreatePost = (params) => actionPromise('PROMISE', 'CreatePost', gql(
  330. `mutation CreatePost($createNewPost: PostInput){
  331. PostUpsert(post: $createNewPost){
  332. _id
  333. }
  334. }`, {
  335. createNewPost: params
  336. }))
  337. // санк для создания поста и последующего перехода на его страницу
  338. export const actionFullCreatePost = (params) =>
  339. async dispatch => {
  340. const newPost = await dispatch(actionCreatePost(params))
  341. // console.log('Тут нужный резульата: ', newPost)
  342. if (newPost) {
  343. dispatch(actionFindPostOne(newPost._id))
  344. }
  345. }