Browse Source

<project>

Евгения Акиншина 2 years ago
parent
commit
ef0fe5af27

+ 6 - 0
src/actions/actionSearch.js

@@ -0,0 +1,6 @@
+import { search } from "./requests";
+import { actionPromise } from "./actionPromise";
+
+export const actionSearch = (string) => async (dispatch) => {
+    return await dispatch(actionPromise('searchSnippet', search(string)))
+};

+ 10 - 0
src/actions/actionSnippetById.js

@@ -0,0 +1,10 @@
+import { actionPromise } from "./actionPromise";
+import { snippetById } from "./requests";
+
+export const actionSnippetById =
+    (id) => async (dispatch) => {
+        return await dispatch(
+            actionPromise("findSnippetById",
+            snippetById(id))
+        )
+    };

+ 6 - 0
src/actions/actionSnippetFindByOwner.js

@@ -0,0 +1,6 @@
+import { actionPromise } from "./actionPromise";
+import { snippetByOwner } from "./requests";
+
+export const actionSnippetFindByOwner = (id) => async (dispatch) => {
+    return await dispatch(actionPromise("findSnippet", snippetByOwner(id)))
+};

+ 9 - 1
src/actions/actionSnippetUpsert.js

@@ -1,4 +1,12 @@
 import { actionPromise } from "./actionPromise";
 import { SnippetUpsert } from "./requests";
 
-export const actionSnippetUpsert = (title, description, files) => actionPromise("SnippetUpsert", SnippetUpsert(title, description, files));
+export const actionSnippetUpsert =
+(title, description, files) => async (dispatch) => {
+  return await dispatch(
+    actionPromise(
+      "SnippetUpsert",
+      SnippetUpsert(title, description, files)
+    )
+  );
+};

+ 61 - 4
src/actions/requests.js

@@ -11,7 +11,7 @@ export const log = async(login, password) => {
     localStorage.authToken = token.data.login
     console.log(token)
     return token.data.login
-}
+};
 
 export const reg = async(login, password) => {
     let query = `mutation reg($login:String!, $password:String!) {
@@ -27,7 +27,7 @@ export const reg = async(login, password) => {
 
     let res = await gql(query, variables)
     return res
-}
+};
 
 export const userFind = (_id) => {
     return gql(
@@ -40,7 +40,7 @@ export const userFind = (_id) => {
     }`,
         { query: JSON.stringify([{ _id }]) }
     )
-}
+};
 
 export const setAva = async (idUser, id) => {
     let query = `mutation setAvatar($idUser:String , $idAvatar:ID){ 
@@ -55,7 +55,7 @@ export const setAva = async (idUser, id) => {
   
     let res = await gql(query, variables)
     return res
-}
+};
 
 export const SnippetUpsert = async (title, description, files) => {
     let query = `mutation SnippetUpsert($snippet:SnippetInput) {
@@ -68,4 +68,61 @@ export const SnippetUpsert = async (title, description, files) => {
   
     let res = await gql(query, variables)
     return res
+};
+
+export const snippetById = async(id) => {
+    let query = `query snippetFind($query:String){
+      SnippetFind(query:$query){
+                        owner{
+                          _id 
+                        }
+            title description _id files {
+             type text name
+           }
+        }
+  }`
+
+    let variables = {query: JSON.stringify([{_id: id }])}
+  
+    let res = gql(query, variables)
+    return res
+};
+
+export const snippetByOwner = async (id) => {
+    let query = `query snippetFind($query:String){
+        SnippetFind(query:$query){
+                          owner{
+                            _id 
+                          }
+              title description _id files {
+               type text name
+            }
+        }
+  }`
+
+    let variables = {query: JSON.stringify([{___owner: id } , {sort:[{_id: -1}]}])}
+  
+    let res = gql(query, variables)
+    return res
+};
+
+export const search = async (string) => {
+    return gql(
+      `query snippetFind($query:String){
+        SnippetFind(query:$query){
+          owner {
+            _id login
+          }
+              title description _id files {
+               type text name
+             }
+          }
+    }`,
+      { query: JSON.stringify([
+        {
+            $or: [{title: `/${string.trim().split(" ").join('|')}/`},{description: `/${string.trim().split(" ").join('|')}/`}] 
+        },
+        {
+          sort: [{title: 1}]}]) }
+    )
 };

+ 10 - 0
src/components/Ava.js

@@ -0,0 +1,10 @@
+import React from "react";
+import { connect } from "react-redux";
+import icon from "../user.png";
+import "./Header.css";
+
+function AvaLogo({ ava }) {
+    return <img src= {ava ? 'http://localhost:3000/' + ava: icon} className = 'avatar' alt=''></img>
+}
+
+export const ConnectedAvaLogo = connect((state) => ({ava: state?.p?.findUser?.payload?.data?.UserFindOne?.avatar?.url}))(AvaLogo);

+ 0 - 10
src/components/Avatar.js

@@ -1,10 +0,0 @@
-import React from "react";
-import { connect } from "react-redux";
-import icon from "../user.png";
-import './Header.css';
-
-function AvaLogo({ link }) {
-    return <img src= {link ? 'http://localhost:3000/' + link: icon} className = 'avatar' alt=''></img>
-}
-
-export const ConnectedAvaLogo = connect((state) => ({link: state?.p?.findUser?.payload?.data?.UserFindOne?.avatar?.url}))(AvaLogo);

+ 2 - 2
src/components/Editor.js

@@ -18,7 +18,7 @@ import "ace-builds/src-noconflict/mode-typescript";
 import "ace-builds/src-noconflict/theme-monokai";
 import "ace-builds/src-noconflict/ext-language_tools";
 import { Select } from "../helpers/Select";
-import './Editor.css'
+import "./Editor.css";
 
 export const Editor = ({ data={type:"", name:"", text:""}, onChange }) => {
     return (
@@ -63,4 +63,4 @@ export const Editor = ({ data={type:"", name:"", text:""}, onChange }) => {
         />
       </div>
     )
-  }
+};

+ 13 - 11
src/components/EditorsPage.js

@@ -1,18 +1,19 @@
-import { useState, useEffect } from 'react';
-import { Editor } from '../components/Editor';
-import './EditorsPage.css';
+import { useState, useEffect } from "react";
+import { Editor } from "../components/Editor";
+import "./EditorsPage.css";
 
 const datas = [{type: "html", name:"", text:'<h1 id="codepen">Welcome to the Codepen</h1>'}, {type: "css", name:"", text:`#codepen {
     color: blue;
     font-size: 25px;
     font-family: Times New Roman;
-  }`}, {type: "javascript", name:"", text:`let btn = document.createElement('button')
-  btn.innerHTML = 'Change color'
-  btn.style.color = 'red'
-  btn.style.fontSize = '20px'
-  document.body.append(btn)
-  btn.style.cursor = 'pointer'
-  btn.onclick = () => {
+}`}, 
+    {type: "javascript", name:"", text:`let btn = document.createElement('button')
+    btn.innerHTML = 'Change color'
+    btn.style.color = 'red'
+    btn.style.fontSize = '20px'
+    document.body.append(btn)
+    btn.style.cursor = 'pointer'
+    btn.onclick = () => {
     document.getElementById('codepen').style.color = 'red'}`}];
 
 export const EditorsPage = ({onSave}) => {
@@ -81,4 +82,5 @@ export const EditorsPage = ({onSave}) => {
         <button className='button_submit' onClick = {() => onSave(title, description, editors)}>Submit this Editor</button>
         </>
 
-    )}
+    )
+};

+ 30 - 1
src/components/Header.css

@@ -11,7 +11,7 @@ nav {
 
 .img_logo {
     width: 100px;
-    margin-right: 1135px;
+    margin-right: 1035px;
     border: 1.5px solid rgb(72, 70, 75);
     margin-top: 10px;
     margin-left: 15px;
@@ -61,4 +61,33 @@ nav {
    margin-right: 10px;
    width: 70px;
    height: 70px;
+}
+
+.button_search {
+    cursor: pointer;
+    margin-top: 50px;
+    margin-right: 10px;
+    position: relative;
+    display: inline-block;
+    width: 6.5em;
+    height: 2.5em;
+    margin-bottom: 5px;
+    vertical-align: middle;
+    font-weight: 550;
+    text-align: center;
+    text-decoration: none;
+    user-select: none;
+    color: rgb(41, 14, 66);
+    outline: none;
+    border: 1px solid rgba(110,121,128,.8);
+    border-top-color: rgba(0,0,0,.3);
+    border-radius: 5px;
+    background: rgb(206, 220, 231) linear-gradient(rgb(206,220,231), rgb(106, 70, 148));
+    box-shadow:
+     0 -1px rgba(10,21,28,.9) inset,
+     0 1px rgba(255,255,255,.5) inset;
+}
+
+.button_search:hover {
+    background: linear-gradient(#baa7cc, #9285b4);
 }

+ 8 - 8
src/components/Header.js

@@ -1,15 +1,15 @@
-import './Header.css';
-import ImgLogo from './Logo';
-import ConnectedNick from './Nick';
+import ImgLogo from "./Logo";
+import ConnectedNick from "./UserHeader";
 import { ConnectFormUpload } from "../pages/FormUpload";
+import "./Header.css";
 
 const Header = () => {
     return (
-<nav className="navbar_header">
-    <ImgLogo />
-    <ConnectFormUpload />
-    <ConnectedNick/>
-</nav>
+    <nav className="navbar_header">
+        <ImgLogo />
+        <ConnectFormUpload />
+        <ConnectedNick/>
+    </nav>
     )
 }
 

+ 12 - 4
src/components/Logo.js

@@ -1,8 +1,16 @@
 import React from "react";
-import logo from '../logo.png'
+import logo from "../logo.png";
+import "./Header.css";
 
 function ImgLogo() {
-    return <a href="/home"> <img src={logo} alt="logo" className='img_logo'/> </a>
-  }
+    return <>
+    <a href="/home"> <img src={logo} alt="logo" className='img_logo'/></a>
+    <a href="/search">
+        <button className='button_search'>
+            Search
+        </button>
+    </a>
+    </>
+}
   
-  export default ImgLogo;
+export default ImgLogo;

+ 0 - 23
src/components/Nick.js

@@ -1,23 +0,0 @@
-import { connect } from "react-redux";
-import { actionAuthLogout } from '../actions/actionAuthLogout';
-import './Header.css';
-
-const NickName = ({ nick, onLogOut }) => {
-    return (
-      <>
-        <div className='logaut'>
-        <a href = '/cabinet'>{nick}
-        </a>
-        <a href="/cabinet">
-            <button className='cabinet'>
-                My Cabinet
-            </button>
-        </a>
-        <a href = '/'><button onClick = {() => (onLogOut())}>Log out</button></a>
-        </div>
-      </>
-      )
-    }
-    
-const ConnectedNick = connect((state) => ({nick: state?.a?.payload?.sub?.login, logedIn: state.a.token}),{onLogOut:actionAuthLogout})(NickName);
-export default ConnectedNick;

+ 0 - 13
src/components/Profile.js

@@ -1,13 +0,0 @@
-import React from "react";
-import wall from "../profileWall.jpeg";
-
-function ImgProfile({ px }) {
-  return (
-    <a href="/">
-      {" "}
-      <img src={wall} alt="wall" style={{ width: px }} />{" "}
-    </a>
-  );
-}
-
-export default ImgProfile;

+ 13 - 11
src/components/Routers.js

@@ -1,14 +1,15 @@
-import React from 'react';
-import { BrowserRouter as Router, Route, Switch, Redirect } from 'react-router-dom';
+import React from "react";
+import { BrowserRouter as Router, Route, Switch, Redirect } from "react-router-dom";
 import createHistory from "history/createBrowserHistory";
-import { connect } from 'react-redux';
-import { actionFullLogin } from '../actions/actionFullLogin';
-import { actionFullRegister } from '../actions/actionFullRegister';
-import { LoginForm } from '../pages/LoginForm';
-import { FormReg } from '../pages/FormReg';
-import { Main } from '../pages/Main';
-import { Home } from '../pages/HomePage';
-import { Cabinet } from '../pages/Cabinet';
+import { connect } from "react-redux";
+import { actionFullLogin } from "../actions/actionFullLogin";
+import { actionFullRegister } from "../actions/actionFullRegister";
+import { LoginForm } from "../pages/LoginForm";
+import { FormReg } from "../pages/FormReg";
+import { Main } from "../pages/Main";
+import { Home } from "../pages/WorkPage";
+import { Cabinet } from "../pages/Cabinet";
+import ConnectFormSearch from "../pages/Search";
 
 const ConnectLoginForm = connect(null, {onLogin:actionFullLogin}) (LoginForm);
 
@@ -24,6 +25,7 @@ const Routs = ({token}) => {
                 <Redirect from="/login" to="/home" />
                 <Route exact path='/home' component={Home} />
                 <Route path='/cabinet' component={Cabinet}/>
+                <Route path='/search' component={ConnectFormSearch}/>
             </Switch>}
             {!token && <Switch>
                 <Route path='/login' component={ConnectLoginForm}/>
@@ -32,7 +34,7 @@ const Routs = ({token}) => {
             </Switch>}
           </Router>
         </div>
-      )
+    )
 }
 
 const ConnectedRouts = connect(state=>({token: state.a.token}), null)(Routs);

+ 8 - 8
src/components/User.js

@@ -2,14 +2,14 @@ import { connect } from "react-redux";
 
 const Nick =  ({nick}) => {
     return (
-      <>
-      <div>
-      <p>{nick}</p>
-      </div>
-      
-      </>
-      )
-    }
+        <>
+        <div>
+            <p>{nick}</p>
+        </div>
+        
+        </>
+    )
+}
     
 const ConnectNickName = connect(state => ({nick: state?.a?.payload?.sub?.login || 0 }))(Nick);
 export default ConnectNickName;

+ 22 - 0
src/components/UserHeader.js

@@ -0,0 +1,22 @@
+import { connect } from "react-redux";
+import { actionAuthLogout } from "../actions/actionAuthLogout";
+import "./Header.css";
+
+const NickName = ({ nick, onLogOut }) => {
+    return (
+      <>
+        <div className='logaut'>
+            <a href = '/cabinet'>{nick}</a>
+            <a href="/cabinet">
+                <button className='cabinet'>
+                    My Cabinet
+                </button>
+            </a>
+            <a href = '/'><button onClick = {() => (onLogOut())}>Log out</button></a>
+        </div>
+      </>
+    )
+}
+    
+const ConnectedNick = connect((state) => ({nick: state?.a?.payload?.sub?.login, logedIn: state.a.token}),{onLogOut:actionAuthLogout})(NickName);
+export default ConnectedNick;

+ 3 - 3
src/pages/Cabinet.js

@@ -1,7 +1,7 @@
 import React from "react";
-import ConnectedNick from '../components/Nick';
-import { ConnectFormUpload } from "./FormUpload";
-import './Main.css';
+import ConnectedNick from "../components/UserHeader";
+import ConnectFormUpload from "./FormUpload";
+import "./Main.css";
 
 export const Cabinet = () => {
   return (

+ 2 - 2
src/pages/FormReg.js

@@ -1,5 +1,5 @@
-import React, {useState} from 'react';
-import './LoginReg.css'
+import React, {useState} from "react";
+import "./LoginReg.css";
 
 export const FormReg = ({FormReg}) => {
     const [login, setLogin] = useState('')

+ 4 - 3
src/pages/FormUpload.js

@@ -1,11 +1,11 @@
 import { connect } from "react-redux";
 import { actionFullAva  } from "../actions/actionFullAva";
 import { useDropzone } from "react-dropzone";
-import { ConnectedAvaLogo } from "../components/Avatar";
+import { ConnectedAvaLogo } from "../components/Ava";
 import "./FormUpload.css";
 
 const FormUpload = ({onUpload}) => {
-    const {acceptedFiles, getRootProps, getInputProps} = useDropzone()
+    const {acceptedFiles, getRootProps, getInputProps} = useDropzone();
     acceptedFiles.map (file => onUpload(file))
     return (
         <div {...getRootProps({})}>
@@ -16,4 +16,5 @@ const FormUpload = ({onUpload}) => {
     )
 }
 
-export const ConnectFormUpload = connect(null, {onUpload:actionFullAva}) (FormUpload);
+export const ConnectFormUpload = connect(null, {onUpload:actionFullAva}) (FormUpload);
+export default ConnectFormUpload;

+ 0 - 16
src/pages/HomePage.js

@@ -1,16 +0,0 @@
-import { EditorsPage } from '../components/EditorsPage';
-import { actionSnippetUpsert } from '../actions/actionSnippetUpsert';
-import { connect }  from 'react-redux';
-import Header from '../components/Header';
-
-export const Home = () => {
-    return (
-    <>
-    <Header />
-    <ConnectEditorsPage />
-    </>
-    )
-}
-
-export const ConnectEditorsPage = connect(null, {onSave:actionSnippetUpsert}) (EditorsPage);
-export default ConnectEditorsPage;

+ 3 - 3
src/pages/LoginForm.js

@@ -1,5 +1,5 @@
-import { useState } from 'react';
-import './LoginReg.css';
+import { useState } from "react";
+import "./LoginReg.css";
 
 export const LoginForm = ({onLogin}) => {
     const [login, setLogin] = useState('')
@@ -13,4 +13,4 @@ export const LoginForm = ({onLogin}) => {
         <button className='main_page'><a href = '/'>Main page</a></button>
         </div>
     )
-}
+};

+ 2 - 11
src/pages/Main.js

@@ -1,4 +1,4 @@
-import './Main.css';
+import "./Main.css";
 
 export const Main = ({history}) => {
     return (
@@ -16,13 +16,4 @@ export const Main = ({history}) => {
             <button className='btn_form' onClick={ () => history.push('./reg') }>Reristration</button>
         </section>
     )
-}
-
-// сделать запросы
-// кабинет
-// страницу с историей эдиторов
-// поиск как его реализовать
-// страница 1 едитора
-// заливка фото пользователя
-
-// тему и прелоадер если останется время
+};

+ 43 - 0
src/pages/Search.js

@@ -0,0 +1,43 @@
+import { actionSearch } from "../actions/actionSearch";
+import { connect } from "react-redux";
+import { useState } from "react";
+
+const Search = ({onSearch , snippets}) => {
+    const [request, setRequest] = useState('');
+  return (
+    <>
+    <div>
+        <a href = '/home'>
+            <button>
+                Back to Work Page
+            </button>
+        </a>
+    </div>
+    <div>
+        <input value={request} onChange={(e) => setRequest(e.target.value)}/>
+        <button onClick = {() => onSearch(request)}>
+            Search
+        </button>
+    </div>
+    {snippets?.map((key, index) => (
+        <div>
+            <h3>
+                {"Project Found"}
+            </h3>
+            <p>
+                <span>Description: </span>
+                {snippets?.[index]?.description}
+            </p>
+            <p>{`Owner: ${snippets?.[index]?.owner?.login}`}</p>
+            <a href ={"/project/" + snippets?.[index]?._id}>
+                <button>Open project</button>
+            </a>
+        </div>
+    ))}
+    </>
+  )
+};
+
+const ConnectFormSearch = connect(state => ({snippets:state?.p?.searchSnippet?.payload?.data?.SnippetFind}) , {onSearch:actionSearch})(Search)
+
+export default ConnectFormSearch;

+ 16 - 0
src/pages/WorkPage.js

@@ -0,0 +1,16 @@
+import { EditorsPage } from "../components/EditorsPage";
+import { actionSnippetUpsert } from "../actions/actionSnippetUpsert";
+import { connect }  from "react-redux";
+import Header from "../components/Header";
+
+export const Home = () => {
+    return (
+    <>
+    <Header />
+    <ConnectEditorsPage />
+    </>
+    )
+}
+
+const ConnectEditorsPage = connect(null, {onSave:actionSnippetUpsert}) (EditorsPage);
+export default ConnectEditorsPage;

+ 1 - 3
src/reducers/auth.js

@@ -1,6 +1,4 @@
-import { decode as atob } from 'base-64';
-
-// функция authReducer
+import { decode as atob } from "base-64";
 
 let signatureToken = (token) => JSON.parse(atob(token.split(".")[1]));
 

+ 4 - 4
src/reducers/index.js

@@ -1,7 +1,7 @@
-import { createStore, combineReducers, applyMiddleware } from 'redux';
-import thunk from 'redux-thunk';
-import authReducer from './auth';
-import promiseReducer from './promise';
+import { createStore, combineReducers, applyMiddleware } from "redux";
+import thunk from "redux-thunk";
+import authReducer from "./auth";
+import promiseReducer from "./promise";
 
 let reducers = combineReducers({
     p: promiseReducer,

+ 1 - 2
src/reducers/promise.js

@@ -1,4 +1,3 @@
-// функция promiseReducer
 function promiseReducer(state = {}, { type, status, payload, error, name }) {
     
     if (type === 'PROMISE') {
@@ -8,7 +7,7 @@ function promiseReducer(state = {}, { type, status, payload, error, name }) {
         }
     }
 
-    return state;
+    return state
 }
 
 export default promiseReducer;