const getGQL = url => { return (query, variables) => { return fetch(url, { method: 'POST', headers: { "content-type": "application/json", ...(localStorage.authToken ? { Authorization: "Bearer " + localStorage.authToken } : {}) }, body: JSON.stringify({ query, variables }), }).then(res => res.json()) } } let gql = getGQL("/graphql") let reg = async (login, password) => { let query = `mutation reg($l: String, $p: String) { UserUpsert(user: { login: $l, password: $p } ) { _id } }` let qVariables = { "l": login, "p": password } let res = await gql(query, qVariables) return res } let log = async (login, password) => { let query = `query log($l: String, $p: String) { login(login: $l, password: $p) }` let qVariables = { "l": login, "p": password } let token = await gql(query, qVariables) return token.data.login } let userChats = async (id) => { let query = `query getUserChats($uid: String){ UserFindOne(query: $uid){ chats{ _id title createdAt lastModified avatar{ _id url } owner{ _id login nick } members{ _id login nick } } } }` let qVariables = { "uid": JSON.stringify([{ "_id": id }]) } let result = await gql(query, qVariables) return result } let chatSortMSG = async (id, skipCount) => { let query = `query getMSG($query: String){ MessageFind(query: $query){ _id text createdAt media{ url _id type } owner{ login _id nick } replyTo { _id text createdAt owner{ login _id nick } } } }` let qVariables = { "query": JSON.stringify([{ "chat._id": id }, { sort: [{ _id: -1 }], skip: [skipCount], limit: [30] }]) } let result = await gql(query, qVariables) return result } let newChat = async (title, members) => { let membersQuery = [] if (Array.isArray(members)) { members.map(member => membersQuery.push({ "_id": member._id })) } let query = `mutation newChat($chat: ChatInput){ ChatUpsert(chat: $chat){ _id title createdAt lastModified owner{ _id login nick } avatar{ _id url } messages { _id text createdAt owner{ login nick } } members{ _id login nick } } }` let qVariables = { "chat": { "title": title, "members": membersQuery } } let result = await gql(query, qVariables) return result } let editChat = async (chat_id, title, members) => { let input = {} input._id = chat_id input.title = title if (members && Array.isArray(members)) { let membersQuery = [] members.map(member => membersQuery.push({ "_id": member._id })) input.members = membersQuery } let query = `mutation editChat($chat: ChatInput){ ChatUpsert(chat: $chat){ _id title members{ _id login nick } avatar { _id url } } }` let qVariables = { "chat": input } let result = await gql(query, qVariables) return result } let avatarSet = async (avatar_id, chat_id) => { let query = `mutation setAvatar($avatar: MediaInput){ MediaUpsert(media: $avatar){ _id text url } }` let qVariables = { "avatar": { "_id": avatar_id, "chatAvatars": { "_id": chat_id } } } let result = await gql(query, qVariables) return result } let newMSG = async (chat_id, text, media, replyTo, forwardTo) => { let input = {} input.text = text input.media = [] input.chat = { "_id": chat_id } if (replyTo) { input.replyTo = { "_id": replyTo } } if (forwardTo) { input.forwarded = { "_id": forwardTo } } if (media && Array.isArray(media)) { media.map(item => input.media.push({ "_id": item._id })) } else { input.media.push({}) } let query = `mutation newMSG($msg: MessageInput){ MessageUpsert(message: $msg){ _id text createdAt owner{ _id nick login } media{ _id url type } } }` let qVariables = { "msg": input } let result = await gql(query, qVariables) return result } let editMSG = async (id, text) => { let input = {} input._id = id input.text = text let query = `mutation editMSG($msg: MessageInput){ MessageUpsert(message: $msg){ _id text media{ _id url } chat{ _id } } }` let qVariables = { "msg": input } let result = await gql(query, qVariables) return result } let userInfo = async (id) => { let query = `query user($uid: String){ UserFindOne(query: $uid){ _id login nick avatar{ _id url } } }` let qVariables = { "uid": JSON.stringify([{ "_id": id }]) } let result = await gql(query, qVariables) return result } let userSearch = async (searchInput) => { let query = `query usrsFND($search: String){ UserFind(query: $search){ _id login nick avatar{ _id url } } }` let qVariables = { "search": JSON.stringify([ { $or: [{ login: `/^${searchInput}/` }, { nick: `/^${searchInput}/` }] }, { sort: [{ login: 1 }] } ]) } let result = await gql(query, qVariables) return result } let changeNick = async (userID, nick) => { let query = `mutation passwordChange($input: UserInput){ UserUpsert(user: $input){ _id } }` let qVariables = { "input": { "_id": userID, "nick": nick } } let result = await gql(query, qVariables) return result } let changeUserAvatar = async (userID, imageID) => { let query = `mutation setUserAvatar($avatar: ImageInput){ ImageUpsert(image: $avatar){ _id text url } }` let qVariables = { "avatar": { "_id": imageID, "userAvatar": { "_id": userID } } } let result = await gql(query, qVariables) return result } let changeUserPassword = async (userID, newPassword) => { let query = `mutation passwordChange($input: UserInput){ UserUpsert(user: $input){ _id } }` let qVariables = { "input": { "_id": userID, "password": newPassword } } let result = await gql(query, qVariables) return result } const actionPending = name => ({ type: 'PROMISE', status: 'PENDING', name }) const actionResolved = (name, payload) => ({ type: 'PROMISE', status: 'RESOLVED', name, payload }) const actionRejected = (name, error) => ({ type: 'PROMISE', status: 'REJECTED', name, error }) const actionPromise = (name, promise) => async dispatch => { dispatch(actionPending(name)) try { let payload = await promise dispatch(actionResolved(name, payload)) return payload } catch (error) { dispatch(actionRejected(name, error)) } } const actionAuthLogin = token => ({ type: "LOGIN", token }) const actionLogin = (login, password) => actionPromise("login", log(login, password)) export const actionFullLogin = (login, password) => { return async (dispatch) => { let result = await dispatch(actionLogin(login, password)) console.log(result) dispatch(actionAuthLogin(result)) } } const actionRegister = (login, password) => actionPromise("register", reg(login, password)) export const actionFullRegister = (login, password) => { return async (dispatch) => { let result = await dispatch(actionRegister(login, password)) console.log(result) if (result.data.UserUpsert !== null) { dispatch(actionFullLogin(login, password)) } } } let upload = async (files) => { let form = new FormData() if (Array.isArray(files)) { files.map(file => form.append("files[]", file)) } else { form.append("media", files) } return fetch("/upload", { method: "POST", headers: localStorage.authToken ? { Authorization: 'Bearer ' + localStorage.authToken } : {}, body: form }).then(res => res.json()) } export const actionChangeUserAvatar = (userID, imageID) => actionPromise("changeUserAvatar", changeUserAvatar(userID, imageID)) export const actionChangeUserPassword = (userID, newPassword) => actionPromise("changeUserPassword", changeUserPassword(userID, newPassword)) export const actionChangeUserNick = (userID, nick) => actionPromise("changeUserNick", changeNick(userID, nick)) export const actionFullChangeUserNick = (userID, nick) => { return async (dispatch) => { let result = await dispatch(actionChangeUserNick(userID, nick)) if (result.data.UserUpsert !== null) { dispatch(actionGetUserInfo(userID)) } } } export const actionFullChangeUserAvatar = (userID, imageID) => { return async (dispatch) => { let result = await dispatch(actionChangeUserAvatar(userID, imageID)) if (result.data.UserUpsert !== null) { dispatch(actionGetUserInfo(userID)) } } } export const actionFullChangeUserPassword = (userID, newPassword) => { return async (dispatch) => { let result = await dispatch(actionChangeUserPassword(userID, newPassword)) if (result.data.UserUpsert !== null) { dispatch(actionGetUserInfo(userID)) } } } export const actionUploadFile = (files) => actionPromise("upload", upload(files)) export const actionAuthLogout = () => ({ type: "LOGOUT" }) export const actionGetUserInfo = (id) => actionPromise("userInfo", userInfo(id)) const actionGetChats = (id) => actionPromise("chats", userChats(id)) const actionGetMessages = (chatID, skipCount) => actionPromise("messages", chatSortMSG(chatID, skipCount)) const actionChats = (chat_id, title, createdAt, lastModified, avatar, messages, members) => ({ type: "CHAT", chat_id, title, createdAt, lastModified, avatar, messages, members }) const actionEditChat = (chat_id, title, avatar, members) => ({ type: "CHAT", chat_id, title, avatar, members }) const actionEditChatBack = (title, avatar, members) => actionPromise("edit_chat", editChat(title, avatar, members)) export const actionEditMSGback = (message_id, text, media) => actionPromise("edit_message", editMSG(message_id, text, media)) export const actionAddChatBack = (title, members) => actionPromise("chat", newChat(title, members)) export const actionAddChat = (chat_id, title, createdAt, lastModified, owner, avatar, messages, members) => ({ type: "CHAT", chat_id, title, createdAt, lastModified, owner, avatar, messages, members }) export const actionAddMSG = (socket, chat_id, msg_id, msg_text, msg_createdAt, msg_owner, msg_media, msg_replyTo) => ({ type: "MESSAGE", socket, chat_id, msg_id, msg_text, msg_createdAt, msg_owner, msg_media, msg_replyTo }) export const actionAddMSGBack = (chat_id, text, media, replyTo, forwardTo) => actionPromise("new_message", newMSG(chat_id, text, media, replyTo, forwardTo)) export const actionSetAvatar = (avatar_id, chat_id) => actionPromise("set_avatar", avatarSet(avatar_id, chat_id)) export const actionUserSearch = (searchInput) => actionPromise("userSearch", userSearch(searchInput)) export const actionFullGetChats = (id) => { return async (dispatch) => { let chats = await dispatch(actionGetChats(id)) chats.data.UserFindOne.chats.map(async (chat) => { dispatch(actionChats(chat._id, chat.title, chat.createdAt, chat.lastModified, chat.avatar, [], chat.members)) }) } } export const actionFullGetMessages = (id, skip) => { return async (dispatch) => { let result = await dispatch(actionGetMessages(id, skip)) let messages = result.data.MessageFind messages.map(message => dispatch(actionAddMSG(false, id, message._id, message.text, message.createdAt, message.owner, message.media, message.replyTo))) } } export const actionFullEditChat = (chat_id, title, avatar, members) => { return async (dispatch) => { let result = await dispatch(actionEditChatBack(chat_id, title, members)) let avatarResult if (avatar) { avatarResult = await dispatch(actionSetAvatar(avatar, chat_id)) } if (result.data.ChatUpsert && avatarResult?.data.MediaUpsert) { dispatch(actionEditChat(chat_id, title, avatarResult.data.MediaUpsert, members)) } else if (result.data.ChatUpsert) { dispatch(actionEditChat(chat_id, title, null, members)) } } }