diff --git a/README.md b/README.md index 40bcee0e7ff1139323b0f3ce82c4c9d65ae76eb5..89b278ae3edb64263849deb1bc26cca15fa96bf2 100644 --- a/README.md +++ b/README.md @@ -1,67 +1,68 @@ -# Formation React +This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). -By Safarte and Soudini +## Available Scripts -## Install +In the project directory, you can run: -* Install NodeJS -* Install yarn -* Run: +### `yarn start` -```bash -git clone https://gitlab.viarezo.fr/LinkCS/react-tutorial-front.git -cd react-tutorial-front -yarn install -``` +Runs the app in the development mode.<br /> +Open [http://localhost:3000](http://localhost:3000) to view it in the browser. -## Usage +The page will reload if you make edits.<br /> +You will also see any lint errors in the console. -You need to complete the code if you want the website to work properly ! +### `yarn test` -To run this website locally execute `yarn start` in the working directory. +Launches the test runner in the interactive watch mode.<br /> +See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. -## API +### `yarn build` -`GET /users => [Object]` -> Lists all users +Builds the app for production to the `build` folder.<br /> +It correctly bundles React in production mode and optimizes the build for the best performance. -`GET /users/id => Object` -> Get the info about the user with asked id +The build is minified and the filenames include the hashes.<br /> +Your app is ready to be deployed! -`GET /boards => [Object]` -> Lists all boards +See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. -`GET /boards/id => Object` -> Get the info about the board with asked id +### `yarn eject` -`GET /messages?board=id => [Object]` -> Get the messages from the board with asked id +**Note: this is a one-way operation. Once you `eject`, you can’t go back!** -To post a message from specified user on specified board: +If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. -```json -POST /messages -body: -{ - "content": "blabla", - "userId": 42, - "boardId": 1 -} -``` +Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. -To register a new user (returns the user): +You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. -```json -POST /users => Object -body: -{ - "username": "henry", - "paswword": "verysecure" -} -``` +## Learn More -To login an user (returns a list containing the matching users): +You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). -```json -POST /login => [Object] -body: -{ - "username": "henry", - "paswword": "verysecure" -} -``` +To learn React, check out the [React documentation](https://reactjs.org/). + +### Code Splitting + +This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting + +### Analyzing the Bundle Size + +This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size + +### Making a Progressive Web App + +This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app + +### Advanced Configuration + +This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration + +### Deployment + +This section has moved here: https://facebook.github.io/create-react-app/docs/deployment + +### `yarn build` fails to minify + +This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify diff --git a/src/App.js b/src/App.js index 23bc14d068451a7d4c20d1fe33520b60a2930cde..02121826b6e5137fdc18a0a825bde80621655001 100644 --- a/src/App.js +++ b/src/App.js @@ -6,21 +6,12 @@ import Board from './components/Board'; import Login from './components/Login'; -// Set this to true in order to use the login page -const USE_LOGIN = false; -// Set this to true in order to use the boards list page -const USE_BOARDSLIST = false; - - -const BoardsListComponent = USE_BOARDSLIST ? BoardsList : Board; -const LoginComponent = USE_LOGIN ? Login : BoardsListComponent; - function App() { return ( <div className='App'> <Switch id='switch'> - <Route exact path='/' component={LoginComponent}/> - <Route exact path='/boards' component={BoardsListComponent}/> + <Route exact path='/' component={Login}/> + <Route exact path='/boards' component={BoardsList}/> <Route path='/board/:id' component={Board}/> </Switch> </div> diff --git a/src/components/Board.js b/src/components/Board.js index 1d06ee1309e818e091bc215aa6f7fb3a5a8c07ee..071fecfef2c84b07879bb60fa030a88dd6ea64ee 100644 --- a/src/components/Board.js +++ b/src/components/Board.js @@ -1,62 +1,156 @@ import React, { useState, useEffect } from 'react'; -import { withRouter } from 'react-router'; +import {withRouter} from 'react-router'; import axios from 'axios'; import { Container, Message, TextArea, Button, Grid, Divider } from 'semantic-ui-react'; const API_URL = 'http://138.195.142.10'; -// Posts a message on a board const postMessage = (message, board) => { - + const request_options = { + url : `${API_URL}/messages`, + method : 'POST', + data: { + userId: parseInt(localStorage.getItem('userId')) || 1, + content: message, + boardId: parseInt(board) + } + }; + return axios.request(request_options); }; -// Gets the list of messages from a board const getMessagesList = async (board) => { - + const request_options = { + method: 'GET', + url: `${API_URL}/messages`, + params: { + board: board + } + }; + return axios.request(request_options).then(resp => resp.data); }; -// Gets the list of users const getUserList = async () => { - + const request_options = { + method: 'GET', + url: `${API_URL}/users` + }; + return axios.request(request_options).then(resp => resp.data); }; -// Gets the data from a board const getBoard = async (id) => { - + const request_options = { + method: 'GET', + url: `${API_URL}/boards`, + params: { + id: id + } + }; + return axios.request(request_options).then(resp => resp.data); }; const Board = (props) => { - // Get the board's id and data + const [id, setId] = useState(-1); + const [board, setBoard] = useState([]); + + useEffect( + () => { + setId(props.location.pathname.split('/')[props.location.pathname.split('/').length-1]) + }, + [props.location.pathname] + ); + + useEffect( + () => { + getBoard(id).then(data => setBoard(data)) + }, + [id] + ); return ( <div> + <Container textAlign='left'> + <Container textAlign='center'><h1>{board[id-1] ? board[id-1].name : ''}</h1></Container> + <Divider/> + <Container> + <MessageWriter board={id}/> + <Divider/> + </Container> + <Container> + <MessageList board={id}/> + </Container> + </Container> </div> ); }; const MessageList = (props) => { - // Get the list of users and initialize the message list - - // Fetch messages every 1 second + const [messages, setMessages] = useState([]); + const [users, setUsers] = useState([]); + + useEffect( + () => { + getMessagesList(props.board).then(data => setMessages(data)); + getUserList().then(data => setUsers(data)); + }, + [props.board] + ); + useEffect( + () => { + const timer = setTimeout(() => { + getMessagesList(props.board).then(data => setMessages(data)); + }, 1000); + return () => clearTimeout(timer); + }, + [messages, props.board] + ); return ( <div> + {messages.map(message => ( + <MessageDisplay message={message} user={users[message.userId-1]}/> + ))} </div> ); }; const MessageDisplay = (props) => { return( - <div> - </div> + <Container> + <Message + key={props.message.id} + header={(props.user ? props.user.username : '') + '@' + props.message.updatedAt.split('T')[1].split('.')[0]} + content={props.message.content} + /> + <Divider/> + </Container> ); }; const MessageWriter = (props) => { - // Initialize a message in the state + const [message, setMessage] = useState(''); return ( <div> + <Container textAlign='center'> + <Grid> + <Grid.Column width='16'> + <Grid.Row> + <TextArea style={{width: '100%'}}onChange={(e) => {setMessage(e.target.value)}} value={message}/> + </Grid.Row> + <Grid.Row> + <Button + style={{width: '100%'}} + onClick={() => {if (message.length) { + setMessage(''); + postMessage(message, props.board); + }}} + > + Send + </Button> + </Grid.Row> + </Grid.Column> + </Grid> + </Container> </div> ); }; diff --git a/src/components/BoardsList.js b/src/components/BoardsList.js index f87c0cbc5eaa89b759a2a3926cdc9f25b3991d8e..778a5bcf246bb6f4a5d3b9a1f5acb931434d335c 100644 --- a/src/components/BoardsList.js +++ b/src/components/BoardsList.js @@ -6,16 +6,34 @@ import { Form, Header } from 'semantic-ui-react'; const API_URL = 'http://138.195.142.10'; -// Gets the list of boards const getBoardList = async () => { - + const request_options = { + method: 'GET', + url: `${API_URL}/boards` + } + return axios.request(request_options).then(resp => resp.data); }; const BoardsList = () => { - // Initialize the list of boards + const [boards, setBoards] = useState([]); + + useEffect( + () => { + getBoardList().then(data => setBoards(data, [])); + }, + [] + ); return ( - <div> + <div style={{ margin: 'auto', maxWidth: '50%', textAlign: 'center', marginTop: '2%' }}> + <Header as='h1'>Boards</Header> + <Form style={{ marginTop: '8%' }}> + {boards.map(board => ( + <Link style={{ margin: '1%' }} to={`/board/${board.id}`}> + <Form.Button fluid content={board.name} /> + </Link> + ))} + </Form> </div> ); }; diff --git a/src/components/Login.js b/src/components/Login.js index d6d49418e6a2e80593b55a9c2c1d03e19f2ca2a4..88269f880d8d79235f648a9c0628a4dc5b8d8bc0 100644 --- a/src/components/Login.js +++ b/src/components/Login.js @@ -5,21 +5,81 @@ import { Form, Image } from 'semantic-ui-react'; const API_URL = 'http://138.195.142.10'; -// Attempts to login and if successful stores the userId in localStorage and redirects to the boards list const handleLogin = async (username, password) => { - + const request_options = { + method: 'POST', + url: `${API_URL}/login`, + data: { + username, + password + } + } + return axios.request(request_options).then(resp => { + const res = resp.data; + if (res.length > 0) { + localStorage.setItem('userId', res[0].id); + return window.location.replace('/boards'); + } + }); }; -// Attempts to register and if successful stores the userId in localStorage and redirects to the boards list const handleRegister = async (username, password) => { - + const request_options = { + method: 'POST', + url: `${API_URL}/users`, + data: { + username, + password + } + } + if (username && password) { + return axios.request(request_options).then(resp => { + if (resp.status === 200) { + console.log(resp); + localStorage.setItem('userId', resp.data.id); + return window.location.replace('/boards'); + } + }); + } }; const Login = () => { - // Initializes username and password in the state + const [username, setUsername] = useState(''); + const [password, setPassword] = useState(''); return ( - <div> + <div style={{ margin: 'auto', maxWidth: '40%', textAlign: 'left' }}> + <Image + style={{ marginLeft: 'auto', marginRight: 'auto', marginTop: '20%', marginBottom: '10%' }} + src='https://gitlab.viarezo.fr/uploads/-/system/project/avatar/1987/react_round_red.png' size='medium' + /> + <Form> + <Form.Input + label='Username' + placeholder='Username' + value={username} + onChange={({ target }) => setUsername(target.value)} + /> + <Form.Input + label='Password' + placeholder='Password' + type='password' + value={password} + onChange={({ target }) => setPassword(target.value)} + /> + <Form.Group widths={2}> + <Form.Button + fluid + content='Login' + onClick={() => handleLogin(username, password)} + /> + <Form.Button + fluid + content='Register' + onClick={() => handleRegister(username, password)} + /> + </Form.Group> + </Form> </div> ); };