From 2896b39b9075db655a0774068bb1bcc7f4fab310 Mon Sep 17 00:00:00 2001 From: Bereczki Sandor <bsandor453@gmail.com> Date: Sun, 20 Jan 2019 02:13:28 +0100 Subject: [PATCH] Homeworks page - task list Listing the tasks based by its properties and states, also counting with empty lists. --- src/actions/homework.js | 30 +++ src/actions/types.js | 3 + src/components/Header.js | 5 + src/components/Main.js | 40 ++-- src/components/pages/Homework.js | 329 ++++++++++++++++++------------- src/reducers/HomeworksReducer.js | 18 ++ src/reducers/index.js | 2 + 7 files changed, 270 insertions(+), 157 deletions(-) create mode 100644 src/actions/homework.js create mode 100644 src/reducers/HomeworksReducer.js diff --git a/src/actions/homework.js b/src/actions/homework.js new file mode 100644 index 0000000..a35110e --- /dev/null +++ b/src/actions/homework.js @@ -0,0 +1,30 @@ +import { axios } from './auth'; +import { GET_HOMEWORKS, GET_SOLUTIONS } from './types'; + +export const getHomeworks = () => ( + async (dispatch) => { + try { + const response = await axios.get('/api/v1/homework/tasks/'); + dispatch({ + type: GET_HOMEWORKS, + payload: response.data, + }); + } catch (e) { + console.log(e); + } + } +); + +export const getSolutions = () => ( + async (dispatch) => { + try { + const response = await axios.get('/api/v1/homework/solutions/'); + dispatch({ + type: GET_SOLUTIONS, + payload: response.data, + }); + } catch (e) { + console.log(e); + } + } +); diff --git a/src/actions/types.js b/src/actions/types.js index 177bbd7..0fa7e52 100644 --- a/src/actions/types.js +++ b/src/actions/types.js @@ -10,3 +10,6 @@ export const ADD_NEWS = 'add_news'; export const DELETE_NEWS = 'delete_news'; export const EDIT_NEWS = 'edit_news'; export const SELECT_NEWS = 'select_news'; + +export const GET_HOMEWORKS = 'get_homeworks'; +export const GET_SOLUTIONS = 'get_solutions'; diff --git a/src/components/Header.js b/src/components/Header.js index e0a9d17..4ea3c7d 100644 --- a/src/components/Header.js +++ b/src/components/Header.js @@ -34,6 +34,11 @@ const menuItems = [ to: '/schedule', prefix: '', }, + { + text: 'HĂĄzi feladatok', + to: '/homework', + prefix: '', + }, ] const FixedMenu = ({ user }) => ( diff --git a/src/components/Main.js b/src/components/Main.js index c24e23e..8307cbb 100644 --- a/src/components/Main.js +++ b/src/components/Main.js @@ -1,27 +1,27 @@ -import React from 'react'; -import { Switch, Route, Redirect, withRouter } from 'react-router-dom'; +import React from "react"; +import { Switch, Route, Redirect, withRouter } from "react-router-dom"; -import Home from './pages/Home'; -import Trainers from './pages/Trainers'; -import Schedule from './pages/Schedule'; -import NotFound from './pages/NotFound'; -import Profile from './pages/Profile'; -import Statistics from './pages/Statistics'; -import Groups from './pages/Groups'; -import News from './pages/News'; -import Homework from './pages/Homework'; +import Home from "./pages/Home"; +import Trainers from "./pages/Trainers"; +import Schedule from "./pages/Schedule"; +import NotFound from "./pages/NotFound"; +import Profile from "./pages/Profile"; +import Statistics from "./pages/Statistics"; +import Groups from "./pages/Groups"; +import News from "./pages/News"; +import Homework from "./pages/Homework"; const Main = () => ( <Switch> - <Redirect exact from='/' to='/home' /> - <Route exact path='/home' component={Home} /> - <Route path='/news' component={News} /> - <Route path='/trainers' component={Trainers} /> - <Route path='/schedule' component={Schedule} /> - <Route path='/profile' component={withRouter(Profile)} /> - <Route path='/statistics' component={Statistics} /> - <Route path='/groups' component={Groups} /> - <Route path='/homework' component={Homework} /> + <Redirect exact from="/" to="/home" /> + <Route exact path="/home" component={Home} /> + <Route path="/news" component={News} /> + <Route path="/trainers" component={Trainers} /> + <Route path="/schedule" component={Schedule} /> + <Route path="/profile" component={withRouter(Profile)} /> + <Route path="/statistics" component={Statistics} /> + <Route path="/groups" component={Groups} /> + <Route path="/homework" component={Homework} /> <Route component={NotFound} /> </Switch> ); diff --git a/src/components/pages/Homework.js b/src/components/pages/Homework.js index ae6a7bf..94aa758 100644 --- a/src/components/pages/Homework.js +++ b/src/components/pages/Homework.js @@ -1,150 +1,205 @@ -import React, { Component } from "react"; +import React, { Component } from 'react'; import { Container, Header, Segment, - Grid, - Image, Table, - Icon -} from "semantic-ui-react"; + Icon, + Message, +} from 'semantic-ui-react'; +import { connect } from 'react-redux'; +import moment from 'moment'; +import { getHomeworks, getSolutions } from '../../actions/homework'; + +const displayTypes = { + can_submit: { + text: 'BeadhatĂł', + icon: 'send', + rowstyle: { warning: false, positive: false, negative: false }, + }, + no_submit: { + text: 'BeadĂĄs elmaradt', + icon: 'warning circle', + rowstyle: { warning: true, positive: false, negative: false }, + }, + wait_correction: { + text: 'JavĂtĂĄsra vĂĄr', + icon: 'wait', + rowstyle: { warning: true, positive: false, negative: false }, + }, + no_accept: { + text: 'Nem elfogadhatĂł', + icon: 'warning circle', + rowstyle: { warning: false, positive: false, negative: true }, + }, + accepted: { + text: 'Elfogadva', + icon: 'checkmark', + rowstyle: { warning: false, positive: true, negative: false }, + }, +}; + +const emptyMessage = (header, text, marginBottom) => ( + <Message + style={{ marginBottom }} + icon='info' + info + header={header} + content={text} + /> +); + +class Homework extends Component { + componentDidMount() { + this.props.getHomeworks(); + this.props.getSolutions(); + } + + getTaskDisplayStyle(task) { + const taskSolutions = this.props.homeworks.solutions.filter(solution => + solution.task === task.id); + + if (taskSolutions.length === 0) { + if (this.isTaskActive(task)) { + return 'can_submit'; + } + + return 'no_submit'; + } + + if (taskSolutions[taskSolutions.length - 1].corrected === false) { + return 'wait_correction'; + } + + if (taskSolutions[taskSolutions.length - 1].accepted === false) { + return 'no_accept'; + } + + return 'accepted'; + } + + isTaskActive(task) { + return moment().isBefore(task.deadline); + } + + renderTaskList(active) { + return this.props.homeworks.tasks + .filter(task => moment().isBefore(task.deadline) === active) + .map(task => ( + <Table.Row + key={task.id} + warning={ + displayTypes[this.getTaskDisplayStyle(task)].rowstyle.warning + } + positive={ + displayTypes[this.getTaskDisplayStyle(task)].rowstyle.positive + } + negative={ + displayTypes[this.getTaskDisplayStyle(task)].rowstyle.negative + } + > + <Table.Cell> + {task.title} <Icon name='external' /> + </Table.Cell> + <Table.Cell> + {moment(task.deadline).format('YYYY. MM. DD. hh:mm')}{' '} + {this.props.homeworks.id} + </Table.Cell> + <Table.Cell> + <Icon name={displayTypes[this.getTaskDisplayStyle(task)].icon} />{' '} + {displayTypes[this.getTaskDisplayStyle(task)].text} + </Table.Cell> + </Table.Row> + )); + } + + renderHomeworksTable(active) { + let tableColor = 'green'; + let marginBottom = '0em'; + + if (!active) { + tableColor = 'blue'; + marginBottom = '3em'; + } + + return ( + <Table color={tableColor} fixed style={{ marginBottom }}> + <Table.Header> + <Table.Row> + <Table.HeaderCell> + <Icon circular name='home' /> + Feladat megnevezĂŠse + </Table.HeaderCell> + <Table.HeaderCell> + <Icon circular name='calendar' /> + BeadĂĄsi hatĂĄridĹ + </Table.HeaderCell> + <Table.HeaderCell> + <Icon circular name='tasks' /> + Ăllapot + </Table.HeaderCell> + </Table.Row> + </Table.Header> + <Table.Body>{this.renderTaskList(active)}</Table.Body> + </Table> + ); + } + + renderHomeworks(active) { + let empty = false; + let emptyText = 'Jelenleg nincs egyetlen beadhatĂł feladat sem. '; + let marginBottom = '0em'; + const emptyHeaderText = 'Nincs feladat.'; + let headerText = 'AktĂv feladatok'; + + if ( + this.props.homeworks.tasks.filter(task => + moment().isBefore(task.deadline) === active).length === 0 + ) { + empty = true; + } + + if (!active) { + headerText = 'LejĂĄrt hatĂĄridejĹą feladatok'; + emptyText = 'Jelenleg nincs egyetlen lejĂĄrt hatĂĄridejĹą feladat sem.'; + marginBottom = '3em'; + } + + return ( + <Segment style={{ padding: '0 0 2em 0' }} vertical basic> + <Container> + <Header + as='h1' + dividing + content={headerText} + style={{ + fontSize: '3em', + fontWeight: 'normal', + marginBottom: 0, + marginTop: '0.5em', + }} + /> + {empty + ? emptyMessage(emptyHeaderText, emptyText, marginBottom) + : this.renderHomeworksTable(active)} + </Container> + </Segment> + ); + } -export default class Homework extends Component { render() { return ( <div> - <Segment inverted textAlign="center" vertical> - <Container> - <Header - as="h1" - content="HĂĄzi feladatok" - inverted - style={{ - fontSize: "3em", - fontWeight: "normal", - marginBottom: 0, - marginTop: "0.5em" - }} - /> - </Container> - </Segment> - <Segment vertical> - <Container> - <Header - as="h1" - dividing - content="AktĂv feladatok" - style={{ - fontSize: "3em", - fontWeight: "normal", - marginBottom: 0, - marginTop: "0.5em" - }} - /> - <Table color="green"> - <Table.Header> - <Table.Row> - <Table.HeaderCell> - <Icon circular name="home" />Feladat megnevezĂŠse - </Table.HeaderCell> - <Table.HeaderCell> - <Icon circular name="calendar" />BeadĂĄsi hatĂĄridĹ - </Table.HeaderCell> - <Table.HeaderCell> - <Icon circular name="tasks" />Ăllapot - </Table.HeaderCell> - </Table.Row> - </Table.Header> - - <Table.Body> - <Table.Row> - <Table.Cell> - Protocols <Icon name="external" /> - </Table.Cell> - <Table.Cell>2018. 03. 05. 23:59</Table.Cell> - <Table.Cell> - <Icon name="send" />BeadhatĂł - </Table.Cell> - </Table.Row> - <Table.Row warning> - <Table.Cell> - Networks <Icon name="external" /> - </Table.Cell> - <Table.Cell>2018. 03. 01. 23:59</Table.Cell> - <Table.Cell> - <Icon name="wait" />JavĂtĂĄsra vĂĄr - </Table.Cell> - </Table.Row> - <Table.Row negative> - <Table.Cell> - Security <Icon name="external" /> - </Table.Cell> - <Table.Cell>2018. 02. 28. 23:59</Table.Cell> - <Table.Cell> - <Icon name="warning circle" />Nem elfogadhatĂł - </Table.Cell> - </Table.Row> - </Table.Body> - </Table> - <Header - as="h1" - dividing - content="LejĂĄrt hatĂĄridejĹą feladatok" - style={{ - fontSize: "3em", - fontWeight: "normal", - marginBottom: 0, - marginTop: "2em" - }} - /> - <Table color="blue"> - <Table.Header> - <Table.Row> - <Table.HeaderCell> - <Icon circular name="home" />Feladat megnevezĂŠse - </Table.HeaderCell> - <Table.HeaderCell> - <Icon circular name="calendar" />BeadĂĄsi hatĂĄridĹ - </Table.HeaderCell> - <Table.HeaderCell> - <Icon circular name="tasks" />Ăllapot - </Table.HeaderCell> - </Table.Row> - </Table.Header> - - <Table.Body> - <Table.Row warning> - <Table.Cell> - BASH <Icon name="external" /> - </Table.Cell> - <Table.Cell>2018. 02. 30. 23:59</Table.Cell> - <Table.Cell> - <Icon name="warning circle" />BeadĂĄs elmaradt - </Table.Cell> - </Table.Row> - <Table.Row positive> - <Table.Cell> - Virtualbox <Icon name="external" /> - </Table.Cell> - <Table.Cell>2018. 02. 25. 23:59</Table.Cell> - <Table.Cell> - <Icon name="checkmark" />Elfogadva - </Table.Cell> - </Table.Row> - <Table.Row positive> - <Table.Cell> - Selfie <Icon name="external" /> - </Table.Cell> - <Table.Cell>2018. 02. 20. 23:59</Table.Cell> - <Table.Cell> - <Icon name="checkmark" />Elfogadva - </Table.Cell> - </Table.Row> - </Table.Body> - </Table> - </Container> - </Segment> + {this.renderHomeworks(true)} + {this.renderHomeworks(false)} </div> ); } } + +const mapStateToProps = ({ homeworks, user }) => ({ homeworks, user }); + +export default connect( + mapStateToProps, + { getHomeworks, getSolutions }, +)(Homework); diff --git a/src/reducers/HomeworksReducer.js b/src/reducers/HomeworksReducer.js new file mode 100644 index 0000000..87e09ee --- /dev/null +++ b/src/reducers/HomeworksReducer.js @@ -0,0 +1,18 @@ +import { GET_HOMEWORKS, GET_SOLUTIONS } from '../actions/types'; + +const INITIAL_STATE = { + tasks: [], + solutions: [], +}; + + +export default (state = INITIAL_STATE, action) => { + switch (action.type) { + case GET_HOMEWORKS: + return { ...state, tasks: action.payload }; + case GET_SOLUTIONS: + return { ...state, solutions: action.payload }; + default: + return state; + } +}; diff --git a/src/reducers/index.js b/src/reducers/index.js index 370c0af..71adb52 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -3,12 +3,14 @@ import UserReducer from './UserReducer'; import NewsReducer from './NewsReducer'; import AddNewsReducer from './AddNewsReducer'; import EditNewsReducer from './EditNewsReducer'; +import HomeworksReducer from './HomeworksReducer'; const rootReducer = combineReducers({ user: UserReducer, news: NewsReducer, newNews: AddNewsReducer, selectedNews: EditNewsReducer, + homeworks: HomeworksReducer, }); export default rootReducer; -- GitLab