瀏覽代碼

added action setAvatar, upload image

makstravm 2 年之前
父節點
當前提交
92b4eb06eb

+ 4 - 4
src/App.js

@@ -3,12 +3,14 @@ import './App.scss';
 import { Router, Route, Switch, Redirect } from 'react-router-dom';
 import createHistory from "history/createBrowserHistory";
 import { connect, Provider } from 'react-redux';
-import { store } from './redux/redux-store';
+import  store  from './redux/redux-store';
 import { Authorization } from './components/Authorization';
 import { Content, Main } from './pages/Content';
 import HeaderComponent from './components/header/Header';
 import { CMainPostFeed } from './components/main/MainPostFeed.js';
 import { CLoginForm, CProfilePage } from './components/main/Profile';
+import { actionAboutMe } from './actions';
+import { CAdd } from './components/main/Add';
 
 export const history = createHistory()
 
@@ -31,10 +33,9 @@ const AppContent = ({ isToken }) =>
                 <Main>
                     <Switch>
                         <Route path='/' component={CMainPostFeed} exact />
-
                         <Route path='/profile/:_id' component={CProfilePage} />
-
                         <Route path='/message' component={Aside} />
+                        <Route path='/add' component={CAdd} />
                         <Redirect from='/*' to='/profile/614c8ef4f9fc3a5e42bddb28' />
                     </Switch>
                 </Main>
@@ -49,7 +50,6 @@ const AppContent = ({ isToken }) =>
     </Router >
 
 const CAppContent = connect(state => ({ isToken: state.auth?.token }))(AppContent)
-
 store.subscribe(() => console.log(store.getState()))
 
 function App() {

+ 58 - 7
src/actions/index.js

@@ -33,14 +33,17 @@ export const actionRegister = (login, password) =>
                                     }
                                 }`, { login, password }))
 
-
-export const actionProfilData = (_id) =>
-    actionPromise('dataProfileAuth', gql(`query userOned($id:String!){
-                        UserFindOne(query: $id){
+export const actionAboutMe = () =>
+    async (dispatch, getState) => {
+        const { auth: { payload: { sub: { id } } } } = getState()
+        await dispatch(actionPromise('dataProfileAuth', gql(`query userOned($myID:String!){
+                        UserFindOne(query: $myID){
                             _id  login nick
                             avatar { _id url }
+                            following{ _id}
                   }
-                }`, { id: JSON.stringify([{ ___owner: _id }]) }))
+                }`, { myID: JSON.stringify([{ ___owner: id }]) })))
+    }
 
 //****************---Action FindUsers ---*************************//
 
@@ -57,7 +60,7 @@ export const actionFindUsers = (value) =>
         {
             sort: [{ login: 1 }]
         },
-            ,])
+        ])
     }))
 
 //****************---Action Like ---*************************//
@@ -123,4 +126,52 @@ export const actionUserPost = (_id) =>
 
 //****************---Action ProfileData ---*************************//
 
-// export const actionSubscribe=()
+
+export const actionUpdateFollowers = (_id) =>
+    actionPromise('upDateFollowers', gql(` query followers($id:String!){
+        UserFindOne(query: $id){
+                            followers {_id nick login}
+        }
+    }`, { id: JSON.stringify([{ _id }]) }))
+
+export const actionSubscribe = (myID, myFollowing, userId) =>
+    actionPromise('subscribe', gql(`mutation following($user:UserInput){
+        UserUpsert( user:$user){
+            following{_id}
+        }
+      }`, { user: { _id: myID, following: [...myFollowing || [], { _id: userId }] } }))
+
+export const actionUnSubscribe = (myID, myFollowing, userId) =>
+    actionPromise('unSubscribe', gql(`mutation followingUn($user:UserInput){
+        UserUpsert( user:$user){
+            following{_id}
+        }
+      }`, { user: { _id: myID, following: [...myFollowing || [], { _id: userId }] } }))
+
+
+
+//****************---Action Upload Images ---*************************//
+
+export const actionSetAvatar = (file) =>
+    async (dispatch, getState) => {
+        // const result = await dispatch(actionUploadFile(file))
+        // if (result) {
+        const { auth: { payload: { sub: { id } } } } = getState()
+        await actionPromise('uploadPhoto', gql(`mutation avaUpsert($ava: UserInput){
+                UserUpsert(user: $ava){
+                    _id avatar {_id}
+                }
+              }`, { ava: { _id: id, avatar: { _id: file._id } } })
+        )
+        await dispatch(actionAboutMe())
+        // }
+    }
+// export const actionUploadFile = (file) => {
+//     let fd = new FormData()
+//     fd.append('photo', file)
+//     return actionPromise('upload', fetch(`${backURL}/upload`, {
+//         method: "POST",
+//         headers: localStorage.authToken ? { Authorization: 'Bearer ' + localStorage.authToken } : {},
+//         body: fd,
+//     }).then(res => res.json()))
+// }

+ 2 - 3
src/components/header/Header.jsx

@@ -10,8 +10,7 @@ import Layout, { Header } from 'antd/lib/layout/layout';
 import { Avatar, Col, Menu, Popover, Row } from 'antd';
 import { UserOutlined, CompassOutlined, SettingOutlined, HomeOutlined, ImportOutlined, MessageOutlined, PlusCircleOutlined } from '@ant-design/icons/lib/icons';
 
-const UserNav = ({ id, profileData }) => {
-    profileData(id)
+const UserNav = ({ id}) => {
     return <div className='UserNav'>
         <CUserNavIcon />
     </div>
@@ -71,7 +70,7 @@ const UserNavIcon = ({ userData: { _id, avatar, login } }) =>
         </Col>
     </Row >
 
-const CUserNav = connect(state => ({ id: state.auth?.payload.sub.id || {} }), { profileData: actionProfilData })(UserNav)
+const CUserNav = connect(state => ({ id: state.auth?.payload.sub.id || {} }) )(UserNav)
 
 const CUserNavIcon = connect(state => ({ userData: state.promise?.dataProfileAuth.payload || {} }))(UserNavIcon)
 

+ 1 - 1
src/components/header/Search.jsx

@@ -28,7 +28,7 @@ export const FieldSearch = ({ usersRes, findUsers }) => {
     return (
         <>
             <Popover placement="bottom" content={<FindUsersResult usersRes={usersRes} />}
-                trigger="click">
+                trigger="focus">
                 <></>
                 <Search className='Header__search'
                     onSearch={value => findUsers(value)}

+ 46 - 0
src/components/main/Add.js

@@ -0,0 +1,46 @@
+import { useState } from 'react';
+import { LoadingOutlined, PlusOutlined } from '@ant-design/icons';
+import { connect } from 'react-redux';
+import { Upload, message} from 'antd';
+import { backURL, gql } from '../../helpers';
+import { actionSetAvatar } from '../../actions';
+
+const Add = ({ imageUrl, onUploadFile }) => {
+    const [loading, setLoading] = useState(false)
+
+    const props = {
+        name: 'photo',
+        action: `${backURL}/upload`,
+        headers: localStorage.authToken ? { Authorization: 'Bearer ' + localStorage.authToken } : {}
+    }
+    const handleChange = async ({ file }) => {
+        if (file.status !== 'uploading') {
+            setLoading(true)
+        }
+        if (file.status === 'done') {
+            message.success(`${file.name} file uploaded successfully`);
+            console.log(1);
+            await onUploadFile(file.response)
+            setLoading(false)
+            console.log(2);
+        } else if (file.status === 'error') {
+            message.error(`${file.name} file upload failed.`);
+        }
+    }
+    return (
+        <Upload {...props}
+            listType="picture-card"
+            showUploadList={false}
+            onChange={handleChange}
+            className="avatar-uploader">
+            {imageUrl ?
+                <img src={`${backURL +'/'+ imageUrl}`} alt="avatar" style={{ width: '100%' }} /> :
+                <div>
+                    {loading ? <LoadingOutlined /> : <PlusOutlined />}
+                    <div style={{ marginTop: 8 }}>Upload</div>
+                </div>}
+        </Upload>
+    )
+}
+
+export const CAdd = connect(state => ({ imageUrl: state.promise?.dataProfileAuth?.payload?.avatar.url }), { onUploadFile: actionSetAvatar })(Add)

+ 12 - 12
src/components/main/Profile.js

@@ -3,7 +3,7 @@ import Modal from 'antd/lib/modal/Modal'
 import React, { useEffect, useState } from 'react'
 import { connect } from 'react-redux'
 import { Link } from 'react-router-dom'
-import { actionProfilePageData } from '../../redux/redux-thunk'
+import { actionFullSubscribe, actionProfilePageData } from '../../redux/redux-thunk'
 import { UserAvatar } from '../header/Header'
 
 const ModalFolower = ({ statusModal, data, title }) => {
@@ -42,22 +42,22 @@ const CModalFollowers = connect(state => ({ data: state?.profileData?.userData?.
 const CModalFollowing = connect(state => ({ data: state?.profileData?.userData?.following || [] }))(ModalFolower)
 
 
-const ProfileSetting = ({myID}) => {
-  useEffect(() => {
-      
-      return () => {
-          
-      }
-  }, [])
+const ProfileSetting = ({ userId, onSubsuscribe }) => {
+    useEffect(() => {
+
+        return () => {
+
+        }
+    }, [])
+    console.log(userId);
     return (
         <Col className='Profile__seting' offset={4}>
-            <Button type="primary">Primary Button</Button>
+            <Button onClick={() => onSubsuscribe(userId)} type="primary">Primary Button</Button>
         </Col>
     )
 }
 
-const CProfileSetting = connect(state => ({ myID: state?.auth?.payload.sub.id,
- }))(ProfileSetting)
+const CProfileSetting = connect(null, { onSubsuscribe: actionFullSubscribe })(ProfileSetting)
 
 const ProfilePageData = ({ data: { _id, avatar, login, nick, followers, following }, posts, setFollowing, setFollowers }) => {
 
@@ -72,7 +72,7 @@ const ProfilePageData = ({ data: { _id, avatar, login, nick, followers, followin
                         <h1>{nick || login || 'No Name'}</h1>
                         <span className='Profile__login'>{login || '----'}</span>
                     </Col>
-                    < CProfileSetting />
+                    < CProfileSetting userId={_id} />
                 </Row>
                 <Row className='Profile__count' align='middle' justify='space-between'>
                     <Col >

+ 1 - 1
src/redux/post-reducer.js

@@ -67,7 +67,7 @@ export const actionMyFolowisgPosts = (skip) =>
             query: JSON.stringify([{},
             {
                 sort: [{ _id: -1 }],
-                skip: [skip +743 ],
+                skip: [skip ],
                 limit: [10]
             }])
         }))

+ 6 - 0
src/redux/profile-reducer.js

@@ -6,6 +6,12 @@ export const profileReducer = (state = {}, { type, userData, userPosts }) => {
             return {
                 ...state, userData, userPosts
             }
+        },
+        'UPDATE-FOLLOWING':()=>{
+            return {
+                ...state,
+                
+            }
         }
     }
     if (type in types) {

+ 6 - 3
src/redux/redux-store.js

@@ -1,14 +1,17 @@
 import { createStore, combineReducers, applyMiddleware } from 'redux';
 import thunk from 'redux-thunk';
+import { actionAboutMe } from '../actions';
 import { authReducer } from './auth-reducer';
 import { postFeedReducer } from './post-reducer';
 import { profileReducer } from './profile-reducer';
 import { promiseReducer } from './promise-reducer';
-
-export const store = createStore(combineReducers({
+const store = createStore(combineReducers({
     promise: promiseReducer,
     auth: authReducer,
     postsFeed: postFeedReducer,
     profileData:profileReducer
 }),
-    applyMiddleware(thunk))
+    applyMiddleware(thunk))
+
+store.dispatch(actionAboutMe())
+export default store;

+ 26 - 10
src/redux/redux-thunk.js

@@ -1,4 +1,4 @@
-import { actionAddComment, actionAddCommentAC, actionAddLikePost, actionAddLikePostAC, actionAddPostsFeedAC, actionAuthLogin, actionFindComment, actionLogin, actionMyLikePost, actionPending, actionRegister, actionRejected, actionRemoveLikePost, actionRemoveLikePostAC, actionResolved, actionUserData, actionUserPost, actionAddProfileDataAC } from "../actions"
+import { actionAddComment, actionAddCommentAC, actionAddLikePost, actionAddLikePostAC, actionAddPostsFeedAC, actionAuthLogin, actionFindComment, actionLogin, actionMyLikePost, actionPending, actionRegister, actionRejected, actionRemoveLikePost, actionRemoveLikePostAC, actionResolved, actionUserData, actionUserPost, actionAddProfileDataAC, actionSubscribe, actionUpdateFollowers, actionAboutMe } from "../actions"
 import { actionMyFolowisgPosts } from "./post-reducer"
 
 export const actionPromise = (name, promise) =>
@@ -15,10 +15,11 @@ export const actionPromise = (name, promise) =>
     }
 
 export const actionFullLogin = (login, password, remember) =>
-    async dispatch => {
-        let token = await dispatch(actionLogin(login, password))
+    async (dispatch) => {
+        const token = await dispatch(actionLogin(login, password))
+        actionAboutMe()
         if (token) {
-            dispatch(actionAuthLogin(token, remember))
+            await dispatch(actionAuthLogin(token, remember))
         }
     }
 
@@ -27,7 +28,7 @@ export const actionFullRegister = (login, password, remember) =>
         await actionRegister(login, password)
         let token = await dispatch(actionLogin(login, password))
         if (token) {
-            dispatch(actionAuthLogin(token, remember))
+            await dispatch(actionAuthLogin(token, remember))
         }
     }
 
@@ -37,7 +38,7 @@ export const actionFullRemoveLikePost = (likeId, postId) =>
         const { likes } = await dispatch(actionMyLikePost(postId))
         console.log(likes);
         if (likes) {
-            dispatch(actionRemoveLikePostAC(postId, likes))
+            await dispatch(actionRemoveLikePostAC(postId, likes))
         }
     }
 
@@ -46,7 +47,7 @@ export const actionFullAddLikePost = (postId) =>
         await actionAddLikePost(postId)
         const { likes } = await dispatch(actionMyLikePost(postId))
         if (likes) {
-            dispatch(actionAddLikePostAC(postId, likes))
+            await dispatch(actionAddLikePostAC(postId, likes))
         }
     }
 
@@ -54,7 +55,7 @@ export const actionAddPostsFeed = (skip) =>
     async dispatch => {
         let posts = await dispatch(actionMyFolowisgPosts(skip))
         if (posts) {
-            dispatch(actionAddPostsFeedAC(posts))
+            await dispatch(actionAddPostsFeedAC(posts))
         }
     }
 
@@ -63,7 +64,7 @@ export const actionFullAddComment = (postId, text) =>
         await actionAddComment(postId, text)
         const { comments } = await dispatch(actionFindComment(postId))
         if (comments) {
-            dispatch(actionAddCommentAC(postId, comments))
+            await dispatch(actionAddCommentAC(postId, comments))
         }
     }
 
@@ -72,6 +73,21 @@ export const actionProfilePageData = (id) =>
         const userData = await dispatch(actionUserData(id))
         const userPosts = await dispatch(actionUserPost(id))
         if (userData, userPosts) {
-            dispatch(actionAddProfileDataAC(userData, userPosts))
+            await dispatch(actionAddProfileDataAC(userData, userPosts))
         }
+    }
+
+export const actionFullSubscribe = (userId) =>
+    async (dispatch, getState) => {
+        const { auth: { payload: { sub: { id } } },
+            promise: { dataProfileAuth: { payload: { following } } } } = getState()
+        console.log(id, following, userId)
+        // actionSubscribe(id, following, userId)
+        const followers = await dispatch(actionUpdateFollowers(userId))
+        console.log(followers);
+        // const userData = await dispatch(actionUserData(id))
+        // const userPosts = await dispatch(actionUserPost(id))
+        // if (userData, userPosts) {
+        //     dispatch(actionAddProfileDataAC(userData, userPosts))
+        // }
     }