2 Commits b8dc560404 ... b2367bd65a

Auteur SHA1 Bericht Datum
  Vadym Hlushko b2367bd65a shit happens 3 jaren geleden
  Vadym Hlushko b8dc560404 login for project 3 jaren geleden

+ 0 - 204
project/src/App.css

@@ -1,204 +0,0 @@
-a:hover,a:focus{
-  outline: none;
-  text-decoration: none;
- }
- .tab{
-  
-  padding: 40px 50px;
-  position: relative;
-  
- }
- .tab:before{
-  content: "";
-  width: 100%;
-  height: 100%;
-  display: block;
-  position: absolute;
-  top: 0;
-  left: 0;
-  background: linear-gradient(#2e3a6a,#2f0b45);
-  opacity: 0.85;
-  border-radius: 50px;
- }
- .tab .nav-tabs{
-  border-bottom: none;
-  padding: 0 20px;
-  position: relative;
- }
- .tab .nav-tabs li{ margin: 0 30px 0 0; }
- .tab .nav-tabs li a{
-  font-size: 18px;
-  color: #fff;
-  border-radius: 0;
-  text-transform: uppercase;
-  background: transparent;
-  padding: 0;
-  margin-right: 0;
-  border: none;
-  border-bottom: 2px solid transparent;
-  opacity: 0.5;
-  position: relative;
-  transition: all 0.5s ease 0s;
- }
- .tab .nav-tabs li a:hover{ background: transparent; }
- .tab .nav-tabs li.active a,
- .tab .nav-tabs li.active a:focus,
- .tab .nav-tabs li.active a:hover{
-  border: none;
-  background: transparent;
-  opacity: 1;
-  border-bottom: 2px solid #eec111;
-  color: #fff;
- }
- .tab .tab-content{
-  padding: 20px 0 0 0;
-  margin-top: 40px;
-  background: transparent;
-  z-index: 1;
-  position: relative;
- }
- .form-bg{ background: #ddd; }
- .form-horizontal .form-group{
-  margin: 0 0 15px 0;
-  position: relative;
- }
- .form-horizontal .form-control{
-  height: 40px;
-  background: rgba(255,255,255,0.2);
-  border: none;
-  border-radius: 20px;
-  box-shadow: none;
-  padding: 0 20px;
-  font-size: 14px;
-  font-weight: bold;
-  color: #fff;
-  transition: all 0.3s ease 0s;
- }
- .form-horizontal .form-control:focus{
-  box-shadow: none;
-  outline: 0 none;
- }
- .form-horizontal .form-group label{
-  padding: 0 20px;
-  color: #7f8291;
-  text-transform: capitalize;
-  margin-bottom: 10px;
- }
- .form-horizontal .main-checkbox{
-  width: 20px;
-  height: 20px;
-  background: #eec111;
-  float: left;
-  margin: 5px 0 0 20px;
-  border: 1px solid #eec111;
-  position: relative;
- }
- .form-horizontal .main-checkbox label{
-  width: 20px;
-  height: 20px;
-  position: absolute;
-  top: 0;
-  left: 0;
-  cursor: pointer;
- }
- .form-horizontal .main-checkbox label:after{
-  content: "";
-  width: 10px;
-  height: 5px;
-  position: absolute;
-  top: 5px;
-  left: 4px;
-  border: 3px solid #fff;
-  border-top: none;
-  border-right: none;
-  background: transparent;
-  opacity: 0;
-  -webkit-transform: rotate(-45deg);
-  transform: rotate(-45deg);
- }
- .form-horizontal .main-checkbox input[type=checkbox]{ visibility: hidden; }
- .form-horizontal .main-checkbox input[type=checkbox]:checked + label:after{ opacity: 1; }
- .form-horizontal .text{
-  float: left;
-  font-size: 14px;
-  font-weight: bold;
-  color: #fff;
-  margin-left: 7px;
-  line-height: 20px;
-  padding-top: 5px;
-  text-transform: capitalize;
- }
- .form-horizontal .btn{
-  width: 100%;
-  background: #eec111;
-  padding: 10px 20px;
-  border: none;
-  font-size: 14px;
-  font-weight: bold;
-  color: #fff;
-  border-radius: 20px;
-  text-transform: uppercase;
-  margin: 20px 0 30px 0;
- }
- .form-horizontal .btn:focus{
-  background: #eec111;
-  color: #fff;
-  outline: none;
-  box-shadow: none;
- }
- .form-horizontal .forgot-pass{
-  border-top: 1px solid #615f6c;
-  margin: 0;
-  text-align: center;
- }
- .form-horizontal .forgot-pass .btn{
-  width: auto;
-  background: transparent;
-  margin: 30px 0 0 0;
-  color: #615f6c;
-  text-transform: capitalize;
-  transition: all 0.3s ease 0s;
- }
- .form-horizontal .forgot-pass .btn:hover{ color: #eec111; }
- @media only screen and (max-width: 479px){
-  .tab{ padding: 40px 20px; }
- }
-
-.App {
-  text-align: center;
-}
-
-.App-logo {
-  height: 40vmin;
-  pointer-events: none;
-}
-
-@media (prefers-reduced-motion: no-preference) {
-  .App-logo {
-    animation: App-logo-spin infinite 20s linear;
-  }
-}
-
-.App-header {
-  background-color: #282c34;
-  min-height: 100vh;
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  justify-content: center;
-  font-size: calc(10px + 2vmin);
-  color: white;
-}
-
-.App-link {
-  color: #61dafb;
-}
-
-@keyframes App-logo-spin {
-  from {
-    transform: rotate(0deg);
-  }
-  to {
-    transform: rotate(360deg);
-  }
-}

+ 0 - 210
project/src/App.js

@@ -1,210 +0,0 @@
-import logo from './logo.svg';
-import './App.css';
-import React, { useState, Component, useEffect, useRef } from "react";
-import {Provider, connect}   from 'react-redux';
-import thunk  from 'redux-thunk';
-import {createStore, combineReducers,applyMiddleware } from 'redux';
-import Form from './components/Form';
-
-
-
-
-
-const getGQL = url => 
-    (query, variables) =>
-        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("http://snippet.asmer.fs.a-level.com.ua/graphql")
-
-function promiseReducer(state , {type, name ,status , payload, error}) {
-  if (!state){
-      return {} //{status , payload , error}
-  }
-  if (type === 'PROMISE') {
-      return {
-          ...state,
-          [name]: [status,payload , error]
-      }
-  }
-  return state
-}
-
-let reg = async(login,password) => {
-  let query = `mutation reg($l:String! , $p:String!) {
-      createUser(login:$l,password:$p){
-  _id
-}
-}`
-
-    let qVariables = {
-      "l": login,
-      "p": password
-    }
-    let result = await gql(query,qVariables)
-    return result
-  }
-
-  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 result = await gql(query,qVariables)
-console.log(result)
-localStorage.authToken = result.data.login
-}
-
-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))
-      }
-  }
-
-  function authReducer(state, action){ //....
-    if (state === undefined){
-        if (!localStorage.authToken){
-            return {}
-        }
-        action.token = localStorage.authToken
-        action.type = 'LOGIN'
-        // добавить в action token из localStorage, и проимитировать LOGIN 
-    }
-    if (action.type === 'LOGIN'){
-        console.log('ЛОГИН')
-        localStorage.authToken = action.token
-        console.log(action.token)
-        function jwt_decode (token) {
-            var start64Url = token.split('.')[1]
-            return JSON.parse(atob(start64Url))
-        }
-        return {token: action.token, payload: jwt_decode(action.token)}
-    }
-    if (action.type === 'LOGOUT'){
-        console.log('ЛОГАУТ')
-        localStorage.removeItem("authToken")
-        //вернуть пустой объект
-        return {}
-    }
-    return state
-}
-
-const actionAuthLogin = token => ({type:'LOGIN', token})
-const actionAuthLogout = () => ({type:'LOGOUT'})
-const actionFullLogin = (login , password) => async dispatch => {
-  let result = await dispatch(actionPromise("login",log(login,password)))
-  if (result.data.login !== null){
-  dispatch(actionAuthLogin(result.data.login))
-  }
-  else {
-      alert ('такого пользователя не существует')
-  }
-}
-const actionRegister = (login,password) => async dispatch => {
-  return await dispatch (actionPromise('register' , reg(login,password)))
-}
-
-const actionFullRegister = (login,password) => async dispatch => {
-  let result =  await dispatch (actionRegister(login,password))
-  if (result.errors === undefined) {
-      await dispatch (actionFullLogin(login,password))
-  }
-  else { 
-      alert("Такой пользователь уже есть")
-
-  }
-}
-
-
-let reducers = {
-    promise:promiseReducer,
-    auth:authReducer
-}
-
-const store = createStore(combineReducers(reducers), applyMiddleware(thunk))
-
-
-
-
-
-const LoginForm = ({ onLogin }) => {
-  const [login, setLogin] = useState("");
-  const [password, setPassword] = useState("");
-  //надо тип инпуту
-  //надо проверку на пустоту инпутов и запрет кнопки (disabled)
-  //надо при кнопке отправить в onLogin login и пароль. onLogin - это функция-колбэк
-  return (
-    <>
-      <input value={login} onChange={(e) => setLogin(e.target.value)} />
-      <input
-        type="password"
-        value={password}
-        onChange={(e) => setPassword(e.target.value)}
-      />
-      <button
-        onClick={() => onLogin(login, password)}
-        disabled={!login || !password}
-      >
-        Sign in
-      </button>
-      
-    </>
-  );
-};
-
-
-const ConnectedLoginForm = connect(null, {onLogin: actionAuthLogin})(LoginForm)
-
-const unsubscribe = store.subscribe(() => console.log('result here',store.getState()))
-
-
-
-const NickName =  ({nick}) => {
-  return (
-    <p></p>,
-    <a href = '#'>{nick || 'anon'}</a>
-    )
-  }
-  
-  
-  
-  const ConnectedNick = connect(state => ({nick:state?.auth?.payload?.sub?.login }))(NickName)
-  
-  const LogOut = connect ((state) => ({children:'Logout' , disabled:!state.auth.token }) , ({onClick:actionAuthLogout}))('button')
-
-
-function App() {
-  return (
-    <div className="App">
-      <Provider store = {store}>
-        <ConnectedNick/> <br/>
-      <ConnectedLoginForm/>
-        <LogOut/>
-        {/* <Form/> */}
-      </Provider>
-     
-    </div>
-  );
-}
-
-export default App;

+ 0 - 57
project/src/components/Form.js

@@ -1,57 +0,0 @@
-import React from "react";
-
-const Form = () => {
-    return (
-        <div className="container">
- <div className="row">
- <div className="col-md-offset-3 col-md-6">
-
- <div className="tab" role="tabpanel">
- <ul className="nav nav-tabs" role="tablist">
- <li role="presentation" className="active"><a href="#Section1" aria-controls="home" role="tab" data-toggle="tab">sign in</a></li>
- <li role="presentation"><a href="#Section2" aria-controls="profile" role="tab" data-toggle="tab">sign up</a></li>
- </ul>
- <div className="tab-content tabs">
- <div role="tabpanel" className="tab-pane fade in active" id="Section1">
- <form className="form-horizontal">
- <div className="form-group">
- <label htmlFor="LogLogin">Login</label>
- <input type="email" className="form-control" id="exampleInputEmail1"/>
- </div>
- <div className="form-group">
- <label htmlFor="LogPassword">Password</label>
- <input type="password" className="form-control" id="exampleInputPassword1"/>
- </div>
- <div className="form-group">
- </div>
- <div className="form-group">
- <button type="submit" className="btn btn-default">Sign in</button>
- </div>
- </form>
- </div>
- <div role="tabpanel" className="tab-pane fade" id="Section2">
- <form className="form-horizontal">
- <div className="form-group">
- <label htmlFor="RegLogin">Login</label>
- <input type="email" className="form-control" id="exampleInputEmail1"/>
- </div>
- <div className="form-group">
- <label htmlFor="RegPassword">Password</label>
- <input type="password" className="form-control" id="exampleInputPassword1"/>
- </div>
- <div className="form-group">
- <button type="submit" className="btn btn-default">Sign up</button>
- </div>
- </form>
- </div>
- </div>
- </div>
-
-</div>
-</div>
-</div>
-    )
-}
-
-export default Form;
-

project/.gitignore → projectreact/.gitignore


project/README.md → projectreact/README.md


File diff suppressed because it is too large
+ 425 - 242
project/package-lock.json


+ 2 - 6
project/package.json

@@ -1,15 +1,15 @@
 {
-  "name": "login",
+  "name": "projectreact",
   "version": "0.1.0",
   "private": true,
   "dependencies": {
     "@testing-library/jest-dom": "^5.14.1",
     "@testing-library/react": "^11.2.7",
     "@testing-library/user-event": "^12.8.3",
-    "graphql-request": "^3.5.0",
     "react": "^17.0.2",
     "react-dom": "^17.0.2",
     "react-redux": "^7.2.5",
+    "react-router-dom": "^5.3.0",
     "react-scripts": "4.0.3",
     "redux": "^4.1.1",
     "redux-thunk": "^2.3.0",
@@ -39,9 +39,5 @@
       "last 1 firefox version",
       "last 1 safari version"
     ]
-  },
-  "devDependencies": {
-    "body-parser": "^1.19.0",
-    "express": "^4.17.1"
   }
 }

project/public/favicon.ico → projectreact/public/favicon.ico


+ 1 - 5
project/public/index.html

@@ -15,8 +15,6 @@
       user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
     -->
     <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
-    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" />
-    
     <!--
       Notice the use of %PUBLIC_URL% in the tags above.
       It will be replaced with the URL of the `public` folder during the build.
@@ -26,7 +24,7 @@
       work correctly both with client-side routing and a non-root public URL.
       Learn how to configure a non-root public URL by running `npm run build`.
     -->
-    <title>login</title>
+    <title>React App</title>
   </head>
   <body>
     <noscript>You need to enable JavaScript to run this app.</noscript>
@@ -41,7 +39,5 @@
       To begin the development, run `npm start` or `yarn start`.
       To create a production bundle, use `npm run build` or `yarn build`.
     -->
-    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
-    <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
   </body>
 </html>

project/public/logo192.png → projectreact/public/logo192.png


project/public/logo512.png → projectreact/public/logo512.png


project/public/manifest.json → projectreact/public/manifest.json


project/public/robots.txt → projectreact/public/robots.txt


+ 38 - 0
projectreact/src/App.css

@@ -0,0 +1,38 @@
+.App {
+  text-align: center;
+}
+
+.App-logo {
+  height: 40vmin;
+  pointer-events: none;
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  .App-logo {
+    animation: App-logo-spin infinite 20s linear;
+  }
+}
+
+.App-header {
+  background-color: #282c34;
+  min-height: 100vh;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  font-size: calc(10px + 2vmin);
+  color: white;
+}
+
+.App-link {
+  color: #61dafb;
+}
+
+@keyframes App-logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}

+ 31 - 0
projectreact/src/App.js

@@ -0,0 +1,31 @@
+import React from 'react';
+import './App.css';
+import createHistory from "history/createBrowserHistory";
+import {Provider, connect}   from 'react-redux';
+import thunk from 'redux-thunk';
+import {createStore, combineReducers, applyMiddleware} from 'redux';
+import store from './reducers';
+import RegForm from './pages/reg';
+import Home from './pages/homePage';
+import {
+  BrowserRouter as Router,
+  Switch,
+  Route, 
+  Link
+} from "react-router-dom";
+
+function App() {
+  return (
+    <div className="App">
+      <Provider store = {store}>
+      <Router history = {createHistory()}>
+      <Route exact path='/' component={Home}/>
+      <Route exact path='/registration' component={RegForm}/>
+      </Router>
+      </Provider>
+     
+    </div>
+  );
+}
+
+export default App;

project/src/App.test.js → projectreact/src/App.test.js


+ 85 - 0
projectreact/src/actions/index.js

@@ -0,0 +1,85 @@
+const getGQL = url => 
+    (query, variables={}) => fetch(url, {
+        method: 'POST',
+        headers: {
+            //Accept: "application/json",
+            "Content-Type": "application/json",
+            ...(localStorage.authToken ? {Authorization: "Bearer " + localStorage.authToken } : {})
+        },
+        body: JSON.stringify({query, variables})
+    }).then(res => res.json())
+
+    let gql = getGQL("/graphql")
+
+export const actionPending = name =>            ({type: "PROMISE" ,status:"PENDING", name})
+export const actionResolved = (name,payload) => ({type: "PROMISE" ,status:"RESOLVED", name,payload})
+export const actionRejected = (name,error) =>   ({type: "PROMISE" ,status:"REJECTED", name,error})
+
+export 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))
+      }
+  }
+
+  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 result = await gql(query,qVariables)
+return result
+}
+
+let reg = async(login,password) => {
+  let query = `mutation reg($l:String! , $p:String!) {
+      createUser(login:$l,password:$p){
+  _id login
+}
+}`
+    let qVariables = {
+      "l":  login,
+      "p": password
+    }
+    let result = await gql(query,qVariables)
+    return result
+  }
+
+
+export const actionAuthLogin = token => ({type:'LOGIN', token})
+export const actionAuthLogout = () => ({type:'LOGOUT'})
+export const actionFullLogin = (login , password) => async dispatch => {
+  let result = await dispatch(actionPromise("login",log(login,password)))
+  if (result?.data?.login !== null){
+  dispatch(actionAuthLogin(result.data.login))
+  }
+  else {
+      alert ('такого пользователя не существует')
+  }
+}
+
+export const actionRegister = (login,password) => async dispatch => {
+        return await dispatch (actionPromise('register' , reg(login,password)))
+     } 
+
+
+export const actionFullRegister = (login,password) => async dispatch => {
+  let result =  await dispatch (actionRegister(login,password))
+  if (result?.errors === undefined) {
+      await dispatch (actionFullLogin(login,password))
+  }
+  else { 
+      alert("Такой пользователь уже есть")
+
+  }
+}
+

+ 8 - 0
projectreact/src/components/future-nick.js

@@ -0,0 +1,8 @@
+const NickName =  ({nick}) => {
+    return (
+      <p></p>,
+      <a href = '#'>{nick || 'anon'}</a>
+      )
+    }
+    
+    const ConnectedNick = connect(state => ({nick:state?.auth?.payload?.sub?.login }))(NickName)

project/src/index.css → projectreact/src/index.css


project/src/index.js → projectreact/src/index.js


project/src/logo.svg → projectreact/src/logo.svg


+ 16 - 0
projectreact/src/pages/homePage.js

@@ -0,0 +1,16 @@
+import React from "react";
+import {connect}   from 'react-redux';
+import {useState} from "react";
+import { Redirect } from "react-router";
+import { Link } from "react-router-dom";
+
+const Home = () =>{
+    return (
+        <>
+        <h1>HOME</h1>
+        <Link to = '/registration'>Reg</Link>
+        </>
+    )
+}
+
+export default Home

+ 0 - 0
projectreact/src/pages/login.js


+ 34 - 0
projectreact/src/pages/reg.js

@@ -0,0 +1,34 @@
+import { connect } from "react-redux";
+import { useState} from "react";
+import { actionFullRegister } from "../actions";
+import { Redirect } from "react-router-dom";
+
+const Reg = ({ onReg }) => {
+    const [login, setLogin] = useState("");
+    const [password, setPassword] = useState("");
+    //надо тип инпуту
+    //надо проверку на пустоту инпутов и запрет кнопки (disabled)
+    //надо при кнопке отправить в onLogin login и пароль. onLogin - это функция-колбэк
+    return (
+      <>
+        <input value={login} onChange={(e) => setLogin(e.target.value)} />
+        <input
+          type="password"
+          value={password}
+          onChange={(e) => setPassword(e.target.value)}
+        />
+        <button
+          onClick={() => onReg(login, password)}
+          disabled={!login || !password}
+        >
+          Sign in
+        </button>
+        
+      </>
+    );
+  };
+  
+  const RegForm = connect(null, {onReg: actionFullRegister})(Reg)
+
+  
+export default RegForm

+ 53 - 0
projectreact/src/reducers/index.js

@@ -0,0 +1,53 @@
+import thunk  from 'redux-thunk'
+import {createStore, combineReducers,applyMiddleware } from 'redux';
+
+function promiseReducer(state , {type, name ,status , payload, error}) {
+  if (!state){
+      return {} //{status , payload , error}
+  }
+  if (type === 'PROMISE') {
+      return {
+          ...state,
+          [name]: [status,payload , error]
+      }
+  }
+  return state
+}
+
+function authReducer(state, action){ //....
+    if (state === undefined){
+        if (!localStorage.authToken){
+            return {}
+        }
+        action.token = localStorage.authToken
+        action.type = 'LOGIN'
+        // добавить в action token из localStorage, и проимитировать LOGIN 
+    }
+    if (action.type === 'LOGIN'){
+        console.log('ЛОГИН')
+        localStorage.authToken = action.token
+        console.log(action.token)
+        function jwt_decode (token) {
+            var start64Url = token.split('.')[1]
+            return JSON.parse(atob(start64Url))
+        }
+        return {token: action.token, payload: jwt_decode(action.token)}
+    }
+    if (action.type === 'LOGOUT'){
+        console.log('ЛОГАУТ')
+        localStorage.removeItem("authToken")
+        //вернуть пустой объект
+        return {}
+    }
+    return state
+}
+
+
+let reducers = {
+    promise:promiseReducer,
+    auth:authReducer
+}
+
+const store = createStore(combineReducers(reducers), applyMiddleware(thunk))
+
+export default store

project/src/reportWebVitals.js → projectreact/src/reportWebVitals.js


project/src/setupTests.js → projectreact/src/setupTests.js