Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • kszk/devteam/kszkepzes/old/kszkepzes-frontend
  • kbgergely/kszkepzes-frontend
2 results
Show changes
Showing
with 1353 additions and 554 deletions
import axios from './session';
import { import {
GET_EVENTS, ABSENT_CHANGE,
GET_EVENT_BY_ID,
GET_TRAINEES,
VISITOR_CHANGE,
WRITE_EVENT,
ADD_EVENT, ADD_EVENT,
CHANGE_NO,
DELETE_EVENT, DELETE_EVENT,
GET_EVENTS,
GET_EVENT_BY_ID,
GET_PROFILES, GET_PROFILES,
GET_SELECTED_PROFILE, GET_SELECTED_PROFILE,
GET_TRAINEES,
SET_STATUS, SET_STATUS,
ABSENT_CHANGE, VISITOR_CHANGE,
CHANGE_NO, WRITE_EVENT,
} from './types'; } from './types';
export const getStaffEvents = () => ( import axios from './session';
async (dispatch) => {
try { export const getStaffEvents = () => async (dispatch) => {
const response = await axios.get('/api/v1/staff_events/'); try {
dispatch({ const response = await axios.get('/api/v1/staff_events/');
type: GET_EVENTS, dispatch({
payload: response.data, type: GET_EVENTS,
}); payload: response.data,
} catch (e) { });
console.log(e); } catch (e) {
} console.log(e);
} }
); };
export const getStudentEvents = () => ( export const getStudentEvents = () => async (dispatch) => {
async (dispatch) => { try {
try { const response = await axios.get('/api/v1/student_events/');
const response = await axios.get('/api/v1/student_events/'); dispatch({
dispatch({ type: GET_EVENTS,
type: GET_EVENTS, payload: response.data,
payload: response.data, });
}); } catch (e) {
} catch (e) { console.log(e);
console.log(e);
}
} }
); };
export const getEventById = id => ( export const getEventById = (id) => async (dispatch) => {
async (dispatch) => { try {
try { const response = await axios.get(`/api/v1/staff_events/${id}`);
const response = await axios.get(`/api/v1/staff_events/${id}`); dispatch({
dispatch({ type: GET_EVENT_BY_ID,
type: GET_EVENT_BY_ID, payload: response.data,
payload: response.data, });
}); } catch (e) {
} catch (e) { console.log(e);
console.log(e);
}
} }
); };
export const getTrainees = () => ( export const getTrainees = () => async (dispatch) => {
async (dispatch) => { try {
try { const response = await axios.get('/api/v1/profiles/');
const response = await axios.get('/api/v1/profiles/'); dispatch({
dispatch({ type: GET_TRAINEES,
type: GET_TRAINEES, payload: response.data,
payload: response.data, });
}); } catch (e) {
} catch (e) { console.log(e);
console.log(e);
}
} }
); };
export const visitorChange = ({ id, value }) => { export const visitorChange = ({ id, value }) => {
switch (value){ switch (value) {
case 'Visitor': case 'Visitor':
return (dispatch => (dispatch({ type: VISITOR_CHANGE, payload: id }))); return (dispatch) => dispatch({ type: VISITOR_CHANGE, payload: id });
case 'Absent': case 'Absent':
return (dispatch => (dispatch({ type: ABSENT_CHANGE, payload: id }))); return (dispatch) => dispatch({ type: ABSENT_CHANGE, payload: id });
case 'No': case 'No':
return (dispatch => (dispatch({ type: CHANGE_NO, payload: id }))); return (dispatch) => dispatch({ type: CHANGE_NO, payload: id });
default: default:
return null;
} }
}; };
export const submitVisitors = ({ id, visitors }) => ( export const submitVisitors = ({ id, visitors, absent }) => async () => {
async () => { try {
try { const response = await axios.patch(`/api/v1/staff_events/${id}/`, {
const response = await axios.patch(`/api/v1/staff_events/${id}/`, { visitors,
visitors absent,
}); });
} catch (e) { if (response.data.id === id) {
console.log(e); return true;
} }
return false;
} catch (e) {
console.log(e);
return false;
} }
); };
export const writeEvent = ({ target: { name, value } }) => (
(dispatch) => {
dispatch({ type: WRITE_EVENT, payload: value, target: name });
}
);
export const writeEvent = ({ target: { name, value } }) => (dispatch) => {
dispatch({ type: WRITE_EVENT, payload: value, target: name });
};
export const eventDate = (name, value) => ( export const eventDate = (name, value) => (dispatch) => {
(dispatch) => { dispatch({ type: WRITE_EVENT, payload: value, target: name });
dispatch({ type: WRITE_EVENT, payload: value, target: name }); };
}
);
export const addEvent = ({ name, date, description }) => ( export const addEvent = ({ name, date, description }) => async (dispatch) => {
async (dispatch) => { try {
try { const response = await axios.post('/api/v1/staff_events/', {
const response = await axios.post('/api/v1/staff_events/', { name,
name, date,
date, description,
description, absent: [],
absent: [], });
if (response.data.id) {
alert('Sikeres mentés!');
dispatch({
type: ADD_EVENT,
payload: response.data,
}); });
if (response.data.id) { } else {
alert('Sikeres mentés!'); alert('Mentés nem sikerült!');
dispatch({
type: ADD_EVENT,
payload: response.data,
});
} else {
alert('Mentés nem sikerült!');
}
} catch (e) {
console.log(e);
} }
} catch (e) {
console.log(e);
} }
); };
export const deleteEvent = event => (
async (dispatch) => {
try {
const response = await axios.delete(`/api/v1/staff_events/${event.id}/`);
if (!response.data.id) {
alert('Sikeres törlés!');
dispatch({
type: DELETE_EVENT,
payload: event,
});
} else {
alert('A törlés nem sikerült!');
}
} catch (e) {
console.log(e);
}
});
export const getProfiles = () => ( export const deleteEvent = (event) => async (dispatch) => {
async (dispatch) => { try {
try { const response = await axios.delete(`/api/v1/staff_events/${event.id}/`);
const response = await axios.get('/api/v1/profiles/'); if (!response.data.id) {
alert('Sikeres törlés!');
dispatch({ dispatch({
type: GET_PROFILES, type: DELETE_EVENT,
payload: response.data, payload: event,
}); });
} catch (e) { } else {
console.log(e); alert('A törlés nem sikerült!');
} }
} catch (e) {
console.log(e);
} }
); };
export const setStatus = (id, status) => ( export const getProfiles = () => async (dispatch) => {
async (dispatch) => { try {
try { const response = await axios.get('/api/v1/profiles/');
const response = await axios.patch(`/api/v1/profiles/${id}/`, { dispatch({
role: status, type: GET_PROFILES,
}); payload: response.data,
if (response.data.id) { });
dispatch({ } catch (e) {
type: SET_STATUS, console.log(e);
payload: response.data,
});
}
} catch (e) {
console.log(e);
}
} }
); };
export const getSelectedProfile = id => ( export const setStatus = (id, status) => async (dispatch) => {
async (dispatch) => { try {
try { const response = await axios.patch(`/api/v1/profiles/${id}/`, {
const response = await axios.get(`/api/v1/profiles/${id}/`); role: status,
});
if (response.data.id) {
dispatch({ dispatch({
type: GET_SELECTED_PROFILE, type: SET_STATUS,
payload: response.data, payload: response.data,
}); });
} catch (e) {
console.log(e);
} }
} catch (e) {
console.log(e);
} }
); };
export const getSelectedProfile = (id) => async (dispatch) => {
try {
const response = await axios.get(`/api/v1/profiles/${id}/`);
dispatch({
type: GET_SELECTED_PROFILE,
payload: response.data,
});
} catch (e) {
console.log(e);
}
};
export const GET_USERDATA = 'get_userdata'; export const GET_USERDATA = 'get_userdata';
export const GET_NEWS = 'get_news'; export const GET_NEWS = 'get_news';
export const GET_DEADLINE = 'get_deadline';
export const GET_GROUPS = 'get_groups';
export const PROFILE_CHANGE = 'profile_change'; export const PROFILE_CHANGE = 'profile_change';
export const GROUP_CHANGE = 'group_change'; export const GROUP_CHANGE = 'group_change';
...@@ -11,9 +14,16 @@ export const DELETE_NEWS = 'delete_news'; ...@@ -11,9 +14,16 @@ export const DELETE_NEWS = 'delete_news';
export const EDIT_NEWS = 'edit_news'; export const EDIT_NEWS = 'edit_news';
export const SELECT_NEWS = 'select_news'; export const SELECT_NEWS = 'select_news';
export const GET_MENTORS = 'get_mentors';
export const GET_IMAGES = 'get_images';
export const GET_TASKS = 'get_homeworks'; export const GET_TASKS = 'get_homeworks';
export const ADD_TASK = 'add_task'; export const ADD_TASK = 'add_task';
export const DELETE_TASK = 'delete_task';
export const EDIT_TASK = 'edit_task';
export const WRITE_TASK = 'write_task'; export const WRITE_TASK = 'write_task';
export const SELECT_TASK = 'select_task';
export const WRITE_SOLUTION = 'write_solution'; export const WRITE_SOLUTION = 'write_solution';
export const WRITE_SOLUTION_FILE = 'write_solution_file'; export const WRITE_SOLUTION_FILE = 'write_solution_file';
export const WRITE_TASK_DEADLINE = 'write_task_deadline'; export const WRITE_TASK_DEADLINE = 'write_task_deadline';
...@@ -22,7 +32,9 @@ export const ADD_SOLUTION = 'add_solution'; ...@@ -22,7 +32,9 @@ export const ADD_SOLUTION = 'add_solution';
export const ADD_DOCUMENT = 'add_document'; export const ADD_DOCUMENT = 'add_document';
export const GET_DOCUMENTS = 'get_documents'; export const GET_DOCUMENTS = 'get_documents';
export const CORRECT_SOLUTION = 'correct_solution'; export const CORRECT_SOLUTION = 'correct_solution';
export const SELECT_SOLUTION = 'select_solution';
export const CHECK = 'check'; export const CHECK = 'check';
export const SETCHECKTRUE = 'setchecktrue';
export const GET_EVENTS = 'get_events'; export const GET_EVENTS = 'get_events';
export const GET_EVENT_BY_ID = 'get_event_by_id'; export const GET_EVENT_BY_ID = 'get_event_by_id';
......
import React from 'react'; import Footer from './Footer';
import Header from './Header'; import Header from './Header';
import Main from './Main'; import Main from './Main';
import Footer from './Footer'; import React from 'react';
const App = () => ( const App = () => (
<div style={{ minHeight: '100%', position: 'relative' }}> <div style={{ minHeight: '100%', position: 'relative', paddingBottom: '3em' }}>
<header id='header' > <header id="header">
<Header /> <Header />
</header> </header>
<main id='main' style={{ minHeight: '100%', position: 'relative' }}> <main id="main" style={{ minHeight: '100%', position: 'relative' }}>
<Main /> <Main />
</main> </main>
<footer id='footer' style={{ position: 'absolute', width: '100%', bottom: '0' }}> <footer
id="footer"
style={{ position: 'absolute', width: '100%', bottom: '0' }}
>
<Footer /> <Footer />
</footer> </footer>
</div> </div>
......
import React from 'react'; import { Container, Segment } from "semantic-ui-react";
import { Container, Segment } from 'semantic-ui-react';
import React from "react";
const Footer = () => ( const Footer = () => (
<Segment inverted vertical textAlign='center' > <Segment inverted vertical textAlign="center">
<Container> <Container>
<p textalign='center' >Created by DevTeam &copy; 2018-2019.</p> <p textalign="center">Created by DevTeam &copy; 2018-2025.</p>
</Container> </Container>
</Segment> </Segment>
); );
export default Footer; export default Footer;
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { import {
Menu,
Container,
Button, Button,
Segment, Container,
Visibility, Icon,
Image, Image,
} from 'semantic-ui-react'; Menu,
import { connect } from 'react-redux'; Popup,
import { getUserData } from '../actions'; Responsive,
import KSZKlogo from './images/kszk_logo.svg'; Segment,
} from "semantic-ui-react";
import React, { Component } from "react";
import KSZKlogo from "./images/kszk_logo.svg";
import { Link } from "react-router-dom";
import { connect } from "react-redux";
import { getUserData } from "../actions";
// Objects that will be converted to menu items in the render method
const menuItems = [ const menuItems = [
{ {
text: 'Főoldal', text: "Főoldal",
to: '/home', to: "/home",
prefix: <Image size='mini' src={KSZKlogo} style={{ marginRight: '1.5em' }} />, prefix: (
<Image size="mini" src={KSZKlogo} style={{ marginRight: "1.5em" }} />
),
permissionLevel: 0, permissionLevel: 0,
}, },
{ {
text: 'Hírek', text: "Hírek",
to: '/news', to: "/news",
prefix: '', prefix: "",
permissionLevel: 0, permissionLevel: 0,
}, },
{ {
text: 'Köreink', text: "Köreink",
to: '/groups', to: "/groups",
prefix: '', prefix: "",
permissionLevel: 0, permissionLevel: 0,
}, },
{ {
text: 'Ütemterv', text: "Ütemterv",
to: '/schedule', to: "/schedule",
prefix: '', prefix: "",
permissionLevel: 1, permissionLevel: 1,
}, },
{ {
text: 'Statisztika', text: "Mentorok",
to: '/statistics', to: "/mentors",
prefix: '', prefix: "",
permissionLevel: 1,
},
{
text: "Statisztika",
to: "/statistics",
prefix: "",
permissionLevel: 3, permissionLevel: 3,
}, },
{ {
text: 'Jelentkezések', text: "Jelentkezések",
to: '/applications', to: "/applications",
prefix: '', prefix: "",
permissionLevel: 3, permissionLevel: 3,
}, },
{ {
text: 'Házi feladatok', text: "Házi feladatok",
to: '/homework', to: "/homework",
prefix: '', prefix: "",
permissionLevel: 1, permissionLevel: 2,
}, },
] ];
const FixedMenu = ({ user }) => (
<Menu fixed='top' size='large' pointing>
<Container>
{menuItems.map((item, i) =>
(user.permission >= item.permissionLevel ||
(item.permissionLevel === 0)
?
<Menu.Item key={i} as={Link} to={item.to}>{item.text}</Menu.Item>
:
null))}
<Menu.Menu position='right'>
<Menu.Item className='item'>
{
user.id ?
<Button.Group>
<Button primary as={Link} to='/profile'>Profilom</Button>
<Button as='a' href='/api/v1/logout/'icon='sign out' />
</Button.Group>
:
<Button as='a' href='/api/v1/login/authsch/' >Bejelentkezés</Button>
}
</Menu.Item>
</Menu.Menu>
</Container>
</Menu>
);
class Header extends Component { class Header extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
visible: false, isOpen: false,
}; };
} }
componentWillMount() {
// Fetch the userData-s
UNSAFE_componentWillMount() {
this.props.getUserData(); this.props.getUserData();
} }
hideFixedMenu() { // Hide the menu after clicking an item on mobile
this.setState({ visible: false }); handleOpen = () => {
} this.setState({ isOpen: true });
};
showFixedMenu() { handleClose = () => {
this.setState({ visible: true }); this.setState({ isOpen: false });
} };
renderHeader(inHeader) {
let renderedItemNum = 0;
let current = 0;
let maxNum = 0;
if (this.props.user.id) {
maxNum = menuItems.filter(
(item) => this.props.user.permission >= item.permissionLevel,
).length;
} else {
maxNum = 3;
}
return (
<Segment inverted textAlign="center" vertical>
<Container>
<Menu inverted secondary size="large">
{/* Default Menu items */}
{menuItems.map((item) => {
if (item.permissionLevel === 0) {
renderedItemNum += 1;
return (
<Menu.Item key={Math.random()} as={Link} to={item.to}>
{item.prefix}
{item.text}
</Menu.Item>
);
}
return null;
})}
{/* After default menu items */}
{menuItems.map((item, i) => {
if (
this.props.user.permission >= item.permissionLevel &&
item.permissionLevel > 0 &&
renderedItemNum < inHeader &&
current < i
) {
renderedItemNum += 1;
current = i;
return (
<Menu.Item key={Math.random()} as={Link} to={item.to}>
{item.prefix}
{item.text}
</Menu.Item>
);
}
return null;
})}
{/* Arrow menu */}
{this.props.user.id && current + 1 < maxNum ? (
<Popup
flowing
hoverable
inverted
trigger={
<Menu.Item>
<Icon name="angle down" size="large" />
</Menu.Item>
}
position="top center"
>
<Menu inverted secondary size="large">
{menuItems.map((item, i) =>
this.props.user.permission >= item.permissionLevel &&
item.permissionLevel > 0 &&
current < i ? (
<Menu.Item key={Math.random()} as={Link} to={item.to}>
{item.prefix}
{item.text}
</Menu.Item>
) : null,
)}
</Menu>
</Popup>
) : null}
{/* Login Button */}
<Menu.Item position="right">
{this.props.user.id ? (
<Button.Group>
<Button inverted as={Link} to="/profile">
Profilom
</Button>
<Button as="a" href="/oidc/logout/" icon="sign out" />
</Button.Group>
) : (
<Button as="a" href="/oidc/authenticate/" inverted>
Bejelentkezés
</Button>
)}
</Menu.Item>
</Menu>
</Container>
</Segment>
);
}
render() { render() {
const { visible } = this.state;
return ( return (
<div> <div>
{visible ? <FixedMenu user={this.props.user} /> : null} {/* Tablet, Computer, ... view */}
<Visibility <Responsive minWidth={600} maxWidth={700}>
onBottomPassed={() => this.showFixedMenu()} {this.renderHeader(3)}
onBottomVisible={() => this.hideFixedMenu()} </Responsive>
once={false} <Responsive minWidth={701} maxWidth={800}>
> {this.renderHeader(4)}
<Segment inverted textAlign='center' vertical> </Responsive>
<Responsive minWidth={801} maxWidth={1000}>
{this.renderHeader(5)}
</Responsive>
<Responsive minWidth={1001} maxWidth={1100}>
{this.renderHeader(6)}
</Responsive>
<Responsive minWidth={1101} maxWidth={1200}>
{this.renderHeader(7)}
</Responsive>
<Responsive minWidth={1201}>{this.renderHeader(8)}</Responsive>
{/* Mobile view */}
<Responsive maxWidth={599}>
<Segment inverted textAlign="center" vertical>
<Container> <Container>
<Menu inverted secondary size='large'> <Menu inverted secondary size="large">
{/* kszk logo + home link */}
{menuItems.map((item, i) => <Menu.Item as={Link} to={menuItems[0].to}>
(this.props.user.permission >= item.permissionLevel || {menuItems[0].prefix}
(item.permissionLevel === 0) ? {menuItems[0].text}
<Menu.Item key={i} as={Link} to={item.to}>{item.prefix}{item.text}</Menu.Item>
:
null))}
<Menu.Item position='right'>
{
this.props.user.id ?
<Button.Group>
<Button inverted as={Link} to='/profile'>Profilom</Button>
<Button as='a' href='/api/v1/logout/' icon='sign out' />
</Button.Group>
:
<Button as='a' href='/api/v1/login/authsch/' inverted>Bejelentkezés</Button>
}
</Menu.Item> </Menu.Item>
{/* Sandwich menu */}
<Popup
flowing
hoverable
inverted
trigger={
<Menu.Item onClick={this.handleClose} position="right">
<Icon name="bars" size="large" />
</Menu.Item>
}
position="top center"
open={this.state.isOpen}
onOpen={this.handleOpen}
on="click"
size="huge"
>
<Menu vertical inverted secondary size="large">
{menuItems.map((item, i) =>
(this.props.user.permission >= item.permissionLevel ||
item.permissionLevel === 0) &&
i > 0 ? (
<Menu.Item
onClick={this.handleClose}
key={Math.random()}
as={Link}
to={item.to}
>
{item.prefix}
{item.text}
</Menu.Item>
) : null,
)}
<Menu.Item>
{this.props.user.id ? (
<Button.Group>
<Button
onClick={this.handleClose}
inverted
as={Link}
to="/profile"
>
Profilom
</Button>
<Button
onClick={this.handleClose}
as="a"
href="/oidc/logout/"
icon="sign out"
/>
</Button.Group>
) : (
<Button
onClick={this.handleClose}
as="a"
href="/oidc/authenticate/"
inverted
>
Bejelentkezés
</Button>
)}
</Menu.Item>
</Menu>
</Popup>
</Menu> </Menu>
</Container> </Container>
</Segment> </Segment>
</Visibility> </Responsive>
</div> </div>
); );
} }
......
import React from 'react'; import { Redirect, Route, Switch, withRouter } from 'react-router-dom';
import { Switch, Route, Redirect, withRouter } from 'react-router-dom';
import ApplicantProfile from './pages/ApplicantProfile';
import Applications from './pages/Applications';
import EventDetail from './pages/EventDetail';
import Groups from './pages/Groups';
import Home from './pages/Home'; import Home from './pages/Home';
import Trainers from './pages/Trainers'; import Homework from './pages/Homework';
import Schedule from './pages/Schedule'; import Mentors from './pages/Mentors';
import News from './pages/News';
import NotFound from './pages/NotFound'; import NotFound from './pages/NotFound';
import Profile from './pages/Profile'; import Profile from './pages/Profile';
import React from 'react';
import Schedule from './pages/Schedule';
import Statistics from './pages/Statistics'; import Statistics from './pages/Statistics';
import Groups from './pages/Groups';
import News from './pages/News';
import Homework from './pages/Homework';
import Applications from './pages/Applications';
import EventDetail from './pages/EventDetail';
import ApplicantProfile from './pages/ApplicantProfile';
const Main = () => ( const Main = () => (
<Switch> <Switch>
<Redirect exact from='/' to='/home' /> <Redirect exact from="/" to="/home" />
<Route exact path='/home' component={Home} /> <Route exact path="/home" component={Home} />
<Route path='/news' component={News} /> <Route path="/news" component={News} />
<Route path='/trainers' component={Trainers} /> <Route path="/mentors" component={Mentors} />
<Route path='/schedule' component={Schedule} /> <Route path="/schedule" component={Schedule} />
<Route path='/profile' component={withRouter(Profile)} /> <Route path="/profile" component={withRouter(Profile)} />
<Route path='/statistics' component={Statistics} /> <Route path="/statistics" component={Statistics} />
<Route path='/groups' component={Groups} /> <Route path="/groups" component={Groups} />
<Route path='/homework' component={Homework} /> <Route path="/homework" component={Homework} />
<Route path='/events/:id' component={EventDetail} /> <Route path="/events/:id" component={EventDetail} />
<Route path='/applications' component={Applications} /> <Route path="/applications" component={Applications} />
<Route path='/applicant/:id' component={ApplicantProfile} /> <Route path="/applicant/:id" component={ApplicantProfile} />
<Route component={NotFound} /> <Route component={NotFound} />
</Switch> </Switch>
); );
......
import { Divider, Header, Segment } from 'semantic-ui-react';
import React, { Component } from 'react';
class GroupCard extends Component {
render() {
return (
<Segment style={{ marginTop: 0 }}>
<Divider style={{ fontSize: '2em' }} horizontal>
<Header as="h3" style={{ fontSize: '1.2em' }}>
{this.props.label}
</Header>
</Divider>
<div
className="paragraph"
dangerouslySetInnerHTML={{ __html: this.props.value }}
/>
</Segment>
);
}
}
export default GroupCard;
import { Button, Form, Icon, Input, Modal } from 'semantic-ui-react';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Modal, Button, Form, Input, TextArea, Icon } from 'semantic-ui-react'; import { addEvent, eventDate, writeEvent } from '../../actions/statistics';
import { connect } from 'react-redux';
import { DateTimeInput } from 'semantic-ui-calendar-react'; import { DateTimeInput } from 'semantic-ui-calendar-react';
import { writeEvent, eventDate, addEvent } from '../../actions/statistics' import { clearWrite } from '../../actions/news';
import { clearWrite } from '../../actions/news' import { connect } from 'react-redux';
class AddEventForm extends Component { class AddEventForm extends Component {
constructor(props) { constructor(props) {
...@@ -14,26 +15,28 @@ class AddEventForm extends Component { ...@@ -14,26 +15,28 @@ class AddEventForm extends Component {
}; };
} }
// Handling change in redux action creator throws an exception // Handling change in redux action creator throws an exception
// Temporal solotion using the components state to display, instead redux state // Temporal solotion using the components state to display, instead redux state
handleChange = (event, {name, value}) => { handleChange = (event, { name, value }) => {
if (this.state.hasOwnProperty(name)) { if (this.state.hasOwnProperty(name)) {
this.setState({ [name]: value }); this.setState({ [name]: value });
} }
this.props.eventDate(name, value) this.props.eventDate(name, value);
} };
render() { render() {
const { name, date, description } = this.props.newEvent; const { name, description } = this.props.newEvent;
return ( return (
<Modal <Modal
open={this.state.showModal} open={this.state.showModal}
trigger={ trigger={
<Button <Button
size='big' size="big"
onClick={() => { this.setState({ showModal: true }); }} onClick={() => {
>Alkalom hozzáadása this.setState({ showModal: true });
}}
>
Alkalom hozzáadása
</Button> </Button>
} }
> >
...@@ -46,26 +49,26 @@ class AddEventForm extends Component { ...@@ -46,26 +49,26 @@ class AddEventForm extends Component {
<Form> <Form>
<Form.Field <Form.Field
control={Input} control={Input}
label='Név' label="Név"
name='name' name="name"
onChange={e => this.props.writeEvent(e)} onChange={(e) => this.props.writeEvent(e)}
value={name} value={name}
style={{ style={{
marginBottom: '20px', marginBottom: '20px',
}} }}
placeholder='Title' placeholder="Title"
/> />
<Form.TextArea <Form.TextArea
name='description' name="description"
label='Leírás:' label="Leírás:"
placeholder='Rövid leírás' placeholder="Rövid leírás"
value={description} value={description}
onChange={e => this.props.writeEvent(e)} onChange={(e) => this.props.writeEvent(e)}
/> />
<DateTimeInput <DateTimeInput
name="date" name="date"
label="Dátum:" label="Dátum:"
dateFormat='YYYY-MM-DD' dateFormat="YYYY-MM-DD"
placeholder="Date" placeholder="Date"
value={this.state.date} value={this.state.date}
iconPosition="left" iconPosition="left"
...@@ -76,22 +79,24 @@ class AddEventForm extends Component { ...@@ -76,22 +79,24 @@ class AddEventForm extends Component {
<Modal.Actions> <Modal.Actions>
<Button <Button
inverted inverted
color='red' color="red"
onClick={() => { this.setState({ showModal: false }); onClick={() => {
this.props.clearWrite();}} this.setState({ showModal: false });
this.props.clearWrite();
}}
> >
<Icon name='remove' /> <Icon name="remove" />
Cancel Cancel
</Button> </Button>
<Button <Button
inverted inverted
color='green' color="green"
onClick={() => { onClick={() => {
this.props.addEvent(this.props.newEvent); this.props.addEvent(this.props.newEvent);
this.setState({ showModal: false, date: '' }); this.setState({ showModal: false, date: '' });
}} }}
> >
<Icon name='checkmark' /> Add <Icon name="checkmark" /> Add
</Button> </Button>
</Modal.Actions> </Modal.Actions>
</Modal> </Modal>
...@@ -101,4 +106,9 @@ class AddEventForm extends Component { ...@@ -101,4 +106,9 @@ class AddEventForm extends Component {
const mapStateToProps = ({ events: { newEvent } }) => ({ newEvent }); const mapStateToProps = ({ events: { newEvent } }) => ({ newEvent });
export default connect(mapStateToProps, { writeEvent, addEvent, eventDate, clearWrite })(AddEventForm); export default connect(mapStateToProps, {
writeEvent,
addEvent,
eventDate,
clearWrite,
})(AddEventForm);
import { Button, Form, Icon, Input, Modal, TextArea } from 'semantic-ui-react';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Modal, Button, Form, Input, TextArea, Icon } from 'semantic-ui-react'; import { clearWrite, postNews, writeNews } from '../../actions/news';
import { connect } from 'react-redux';
import { postNews, writeNews, clearWrite } from '../../actions/news'; import { connect } from 'react-redux';
class AddNewsForm extends Component { class AddNewsForm extends Component {
constructor(props) { constructor(props) {
...@@ -14,15 +14,18 @@ class AddNewsForm extends Component { ...@@ -14,15 +14,18 @@ class AddNewsForm extends Component {
render() { render() {
const { title, text } = this.props.newNews; const { title, text } = this.props.newNews;
const author = this.props.user.id; const updated_by = this.props.user.id;
return ( return (
<Modal <Modal
open={this.state.showModal} open={this.state.showModal}
trigger={ trigger={
<Button <Button
size='big' size="big"
onClick={() => { this.setState({ showModal: true }); }} onClick={() => {
>Hír hozzáadása this.setState({ showModal: true });
}}
>
Hír hozzáadása
</Button> </Button>
} }
> >
...@@ -31,41 +34,43 @@ class AddNewsForm extends Component { ...@@ -31,41 +34,43 @@ class AddNewsForm extends Component {
<Form> <Form>
<Form.Field <Form.Field
control={Input} control={Input}
label='Title' label="Title"
name='title' name="title"
onChange={e => this.props.writeNews(e)} onChange={(e) => this.props.writeNews(e)}
value={title} value={title}
placeholder='Title' placeholder="Title"
/> />
<Form.Field <Form.Field
control={TextArea} control={TextArea}
label='Text' label="Text"
name='text' name="text"
onChange={e => this.props.writeNews(e)} onChange={(e) => this.props.writeNews(e)}
value={text} value={text}
placeholder='Tell us what you want...' placeholder="Tell us what you want..."
/> />
</Form> </Form>
</Modal.Content> </Modal.Content>
<Modal.Actions> <Modal.Actions>
<Button <Button
inverted inverted
color='red' color="red"
onClick={() => { this.setState({ showModal: false }); }} onClick={() => {
this.setState({ showModal: false });
}}
> >
<Icon name='remove' /> <Icon name="remove" />
Cancel Cancel
</Button> </Button>
<Button <Button
inverted inverted
color='green' color="green"
onClick={() => { onClick={() => {
this.props.postNews({ title, text, author }); this.props.postNews({ title, text, updated_by });
this.setState({ showModal: false }); this.setState({ showModal: false });
this.props.clearWrite(); this.props.clearWrite();
}} }}
> >
<Icon name='checkmark' /> Add <Icon name="checkmark" /> Add
</Button> </Button>
</Modal.Actions> </Modal.Actions>
</Modal> </Modal>
...@@ -75,4 +80,6 @@ class AddNewsForm extends Component { ...@@ -75,4 +80,6 @@ class AddNewsForm extends Component {
const mapStateToProps = ({ newNews, user }) => ({ newNews, user }); const mapStateToProps = ({ newNews, user }) => ({ newNews, user });
export default connect(mapStateToProps, { postNews, writeNews, clearWrite })(AddNewsForm); export default connect(mapStateToProps, { postNews, writeNews, clearWrite })(
AddNewsForm
);
import './Forms.css';
import {
Button,
Dimmer,
Divider,
Form,
Header,
Icon,
Input,
Loader,
Modal,
Segment,
TextArea,
} from 'semantic-ui-react';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Modal, Button, Form, Input, TextArea, Icon, Header } from 'semantic-ui-react'; import {
addDocument,
addSolution,
clearWrite,
getDocuments,
getSolutions,
writeSolution,
writeSolutionFile,
} from '../../actions/homework';
import ConfirmModal from './ConfirmModal';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { addSolution, writeSolution, writeSolutionFile, addDocument, clearWrite } from '../../actions/homework'; import { customMessage } from '../pages/Homework';
const allowedFileTypes = [
'image/jpeg',
'image/png',
'application/zip',
'application/x-zip',
];
const allowedFileEnds = ['.zip', '.jpeg', '.jpg', '.jpe', '.png'];
function validateFileName(fileNameToValidate) {
return (
allowedFileEnds.find((typeName) => {
return fileNameToValidate.toLowerCase().endsWith(typeName);
}).length > 0
);
}
// in megabytes
const maxFileSize = 50;
class AddSolutionForm extends Component { class AddSolutionForm extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
showModal: false, showModal: false,
loading: false,
}; };
} }
render() { render() {
const { const { name, description, file } = this.props.newSolution;
name, description, file,
} = this.props.newSolution;
const task = this.props.taskid; const task = this.props.taskid;
const thisTaskSolution = this.props.homeworks.solutions.filter(
(solution) => solution.task === task
);
const thisTaskDocument = this.props.homeworks.documents.filter(
(document) => document.solution === thisTaskSolution[0]?.id
);
const lastName = thisTaskDocument[0]?.name;
const lastDesc = thisTaskDocument[0]?.description;
const lastFile = thisTaskDocument[0]?.file_url;
const corrected = false; const corrected = false;
const accepted = false; const accepted = false;
const sentences = this.props.taskdesc.split('\n'); const sentences = this.props.taskdesc.split('\n');
const note = ''; const note = '';
const disabledText = 'A határidő lejárt, további beadás nem lehetséges.';
return ( return (
<Modal <Modal
open={this.state.showModal} open={this.state.showModal}
closeOnDimmerClick
onClose={() => this.setState({ showModal: false })}
trigger={ trigger={
<Button basic color='blue' onClick={() => { this.setState({ showModal: true }); }}> <button
<Icon name='external' /> type="button"
id="task"
onClick={() => {
this.setState({ showModal: true });
}}
>
<Icon name="external" />
{this.props.tasktitle} {this.props.tasktitle}
</Button> </button>
} }
> >
<Modal.Header> <Modal.Header>
Új megoldás beadása a(z) {this.props.tasktitle} nevű feladathoz: {this.props.multiple ? 'Másik megoldás' : 'Megoldás'} beadása a(z)
{this.props.tasktitle} nevű feladathoz:
</Modal.Header> </Modal.Header>
<Modal.Content> <Modal.Content>
<Modal.Description style={{ marginBottom: '2em' }}> <Modal.Description style={{ marginBottom: '2em' }}>
<Header as='h5'>Feladat leírása:</Header> <Header as="h5">Feladat leírása:</Header>
{sentences.map(s => (<p>{s}</p>))} {sentences.map((s) => (
<p key={Math.random()}>{s}</p>
))}
</Modal.Description> </Modal.Description>
<Form> {this.props.disabled ? (
<Form.Field <div>
control={Input} {lastName ? (
label='Megoldás címe:' <div style={{ paddingBottom: '1em' }}>
name='name' <div style={{ marginBottom: '1em', fontWeight: 'bold' }}>
onChange={e => this.props.writeSolution(e)} Legutóbbi megoldásod:
value={name} </div>
placeholder='Adj meg egy címet a beadandó megoldásodnak...' <Segment attached="top">
/> <h5 style={{ paddingBottom: '0.4em' }}>Cím:</h5>
<Form.Field {lastName}
control={TextArea} </Segment>
label='Megoldás leírása:' <Segment attached>
name='description' <h5 style={{ paddingBottom: '0.4em' }}>Leírás:</h5>
onChange={e => this.props.writeSolution(e)} {lastDesc}
value={description} </Segment>
placeholder='Add meg a megoldás leírását...' <Segment attached="bottom">
/> <h5>Beadott fájl:</h5>
<Form.Field> {lastFile ? (
<label>Fájl:</label> <a href={lastFile} rel="noreferrer noopener" download>
<Input type='file' onChange={e => this.props.writeSolutionFile(e)} /> Fájl letöltése
</Form.Field> </a>
</Form> ) : (
<span>-</span>
)}
</Segment>
</div>
) : (
customMessage(
disabledText,
undefined,
undefined,
this.props.disabled
)
)}
</div>
) : (
<Form>
{lastName ? (
<div style={{ paddingBottom: '1em' }}>
<div style={{ fontWeight: 'bold' }}>
Legutóbbi megoldásod:
</div>
<Segment attached="top">
<h5 style={{ paddingBottom: '0.4em' }}>Cím:</h5>
{lastName}
</Segment>
<Segment attached>
<h5 style={{ paddingBottom: '0.4em' }}>Leírás:</h5>
{lastDesc}
</Segment>
<Segment attached="bottom">
<h5>Beadott fájl:</h5>
{lastFile ? (
<a href={lastFile} rel="noreferrer noopener" download>
Fájl letöltése
</a>
) : (
<span>-</span>
)}
</Segment>
</div>
) : null}
<Divider />
<Form.Field
control={Input}
label="Megoldás címe:"
name="name"
onChange={(e) => this.props.writeSolution(e)}
value={name}
placeholder="Adj meg egy címet a beadandó megoldásodnak..."
/>
<Form.Field
control={TextArea}
label="Megoldás leírása:"
name="description"
onChange={(e) => this.props.writeSolution(e)}
value={description}
placeholder="Add meg a megoldás leírását..."
/>
<Form.Field>
<label>
Fájl (Megengedett fájltípusok: png, jpeg, jpg, zip. Maximum 50
MB.):
</label>
<Input
type="file"
accept={allowedFileTypes.join(',')}
onChange={(e) => this.props.writeSolutionFile(e)}
/>
</Form.Field>
</Form>
)}
</Modal.Content> </Modal.Content>
<Modal.Actions> <Modal.Actions>
<Button <Button
inverted inverted
color='red' color="red"
onClick={() => { onClick={() => {
this.setState({ showModal: false }); this.setState({ showModal: false });
this.props.clearWrite();
}} }}
> >
<Icon name='remove' /> Mégse <Icon name="remove" /> Mégse
</Button> </Button>
<Button {this.props.multiple ? (
inverted <ConfirmModal
color='green' button={
onClick={() => { <Button
this.props.addSolution({ disabled={
task, accepted, corrected, note, name, description, file, !name ||
}); !description ||
this.setState({ showModal: false }); (!file
? false
: !validateFileName(file.name) ||
file.size > maxFileSize * 1024 ** 2)
}
inverted
color="green"
>
<Icon name="checkmark" />
Beadás
{this.state.loading ? (
<Dimmer active>
<Loader size="massive" />
</Dimmer>
) : null}
</Button>
}
text="beadod az új megoldást, ami felülírja az előzőt"
onAccept={() => {
this.setState({
loading: true,
});
this.props
.addSolution({
task,
accepted,
corrected,
note,
name,
description,
file,
})
.then(
() => {
this.setState({
loading: false,
showModal: false,
});
this.props.clearWrite();
},
() => {
this.setState({
loading: false,
});
alert('Sikertelen feltöltés!');
}
)
.finally(() => {
window.location.reload(false);
});
}} }}
> />
<Icon name='checkmark' /> Beadás ) : (
</Button> <Button
inverted
color="green"
disabled={
!name ||
!description ||
(!file
? false
: !validateFileName(file.name) ||
file.size > maxFileSize * 1024 ** 2)
}
onClick={() => {
this.props.addSolution({
task,
accepted,
corrected,
note,
name,
description,
file,
});
this.setState({ showModal: false });
this.props.clearWrite();
}}
>
<Icon name="checkmark" /> Beadás
</Button>
)}
</Modal.Actions> </Modal.Actions>
</Modal> </Modal>
); );
} }
} }
const mapStateToProps = ({ newSolution, homeworks, user }) => ({ newSolution, homeworks, user }); const mapStateToProps = ({ newSolution, homeworks, user }) => ({
newSolution,
homeworks,
user,
});
export default connect(mapStateToProps, { export default connect(mapStateToProps, {
addSolution, addSolution,
writeSolution, writeSolution,
writeSolutionFile, writeSolutionFile,
addDocument, addDocument,
getDocuments,
clearWrite, clearWrite,
getSolutions,
})(AddSolutionForm); })(AddSolutionForm);
import {
Button,
Form,
Icon,
Input,
Modal,
TextArea,
} from 'semantic-ui-react';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Modal, Button, Form, Input, TextArea, Icon } from 'semantic-ui-react'; import {
import { connect } from 'react-redux'; addTask,
clearWrite,
writeTask,
writeTaskDeadline,
} from '../../actions/homework';
import { DateTimeInput } from 'semantic-ui-calendar-react'; import { DateTimeInput } from 'semantic-ui-calendar-react';
import { addTask, writeTask, writeTaskDeadline, clearWrite } from '../../actions/homework'; import { connect } from 'react-redux';
import moment from 'moment';
class AddTaskForm extends Component { class AddTaskForm extends Component {
constructor(props) { constructor(props) {
...@@ -13,20 +27,26 @@ class AddTaskForm extends Component { ...@@ -13,20 +27,26 @@ class AddTaskForm extends Component {
} }
render() { render() {
const { title, text, deadline } = this.props.newTask; const {
title, text, deadline, bits = 1,
} = this.props.newTask;
return ( return (
<Modal <Modal
open={this.state.showModal} open={this.state.showModal}
trigger={ closeOnDimmerClick
onClose={() => this.setState({ showModal: false })}
trigger={(
<Button <Button
inverted inverted
style={{ marginRight: '2em' }} style={{ marginRight: '2em' }}
color='blue' color='blue'
onClick={() => { this.setState({ showModal: true }); }} onClick={() => { this.setState({ showModal: true }); }}
> >
<Icon name='plus' /> Új feladat hozzáadása <Icon name='plus' />
{' '}
Új feladat hozzáadása
</Button> </Button>
} )}
> >
<Modal.Header>Új feladat:</Modal.Header> <Modal.Header>Új feladat:</Modal.Header>
<Modal.Content> <Modal.Content>
...@@ -35,7 +55,7 @@ class AddTaskForm extends Component { ...@@ -35,7 +55,7 @@ class AddTaskForm extends Component {
control={Input} control={Input}
label='Cím:' label='Cím:'
name='title' name='title'
onChange={e => this.props.writeTask(e)} onChange={(e) => this.props.writeTask(e)}
value={title} value={title}
placeholder='Add meg a feladat címét.' placeholder='Add meg a feladat címét.'
/> />
...@@ -43,13 +63,13 @@ class AddTaskForm extends Component { ...@@ -43,13 +63,13 @@ class AddTaskForm extends Component {
control={TextArea} control={TextArea}
label='Leírás:' label='Leírás:'
name='text' name='text'
onChange={e => this.props.writeTask(e)} onChange={(e) => this.props.writeTask(e)}
value={text} value={text}
placeholder='Add meg a feladat leírását...' placeholder='Add meg a feladat leírását...'
/> />
<Form.Field <Form.Field
control={DateTimeInput} control={DateTimeInput}
label='Beadási határidő:' label='Beadási határidő (a jelenlegi időnél későbbi időpont):'
name='deadline' name='deadline'
placeholder='Beadási határidő' placeholder='Beadási határidő'
iconPosition='left' iconPosition='left'
...@@ -59,6 +79,15 @@ class AddTaskForm extends Component { ...@@ -59,6 +79,15 @@ class AddTaskForm extends Component {
}} }}
value={deadline} value={deadline}
/> />
<Form.Field
control={Input}
type='number'
label='Bitek száma:'
name='bits'
onChange={(e) => this.props.writeTask(e)}
value={bits}
placeholder='Add meg a feladatért kapható bitek számát ...'
/>
</Form> </Form>
</Modal.Content> </Modal.Content>
<Modal.Actions> <Modal.Actions>
...@@ -70,18 +99,30 @@ class AddTaskForm extends Component { ...@@ -70,18 +99,30 @@ class AddTaskForm extends Component {
this.props.clearWrite(); this.props.clearWrite();
}} }}
> >
<Icon name='remove' /> Mégse <Icon name='remove' />
{' '}
Mégse
</Button> </Button>
<Button <Button
inverted inverted
color='green' color='green'
disabled={
title === ''
|| title.length > 150
|| text === ''
|| deadline === '' || moment().isAfter(deadline)
}
onClick={() => { onClick={() => {
this.props.addTask({ title, text, deadline }); this.props.addTask({
title, text, deadline, bits,
});
this.setState({ showModal: false }); this.setState({ showModal: false });
this.props.clearWrite(); this.props.clearWrite();
}} }}
> >
<Icon name='checkmark' /> Hozzáadás <Icon name='checkmark' />
{' '}
Hozzáadás
</Button> </Button>
</Modal.Actions> </Modal.Actions>
</Modal> </Modal>
......
import React, { Component } from 'react';
import { Button, Header, Icon, Modal } from 'semantic-ui-react'; import { Button, Header, Icon, Modal } from 'semantic-ui-react';
import React, { Component } from 'react';
class ConfirmModal extends Component { class ConfirmModal extends Component {
constructor(props) { constructor(props) {
...@@ -9,9 +9,9 @@ class ConfirmModal extends Component { ...@@ -9,9 +9,9 @@ class ConfirmModal extends Component {
}; };
} }
close = () => this.setState({ showModal: false }) close = () => this.setState({ showModal: false });
open = () => this.setState({ showModal: true}) open = () => this.setState({ showModal: true });
render() { render() {
const { button, text, onAccept } = this.props; const { button, text, onAccept } = this.props;
...@@ -23,34 +23,26 @@ class ConfirmModal extends Component { ...@@ -23,34 +23,26 @@ class ConfirmModal extends Component {
trigger={button} trigger={button}
onOpen={this.open} onOpen={this.open}
onClose={this.close} onClose={this.close}
size='small' size="small"
basic basic
> >
<Header icon='question' content='Confirm' /> <Header icon="question" content="Megerősítés" />
<Modal.Content> <Modal.Content>
<p> <p>Biztos hogy {text}?</p>
Biztos hogy {text}?
</p>
</Modal.Content> </Modal.Content>
<Modal.Actions> <Modal.Actions>
<Button <Button basic color="red" inverted onClick={() => this.close()}>
basic <Icon name="remove" /> Nem
color='red'
inverted
inverted
onClick={() => this.close()}
>
<Icon name='remove' /> No
</Button> </Button>
<Button <Button
color='green' color="green"
inverted inverted
onClick={() => { onAccept(); onClick={() => {
this.close(); onAccept();
} this.close();
} }}
> >
<Icon name='checkmark' /> Yes <Icon name="checkmark" /> Igen
</Button> </Button>
</Modal.Actions> </Modal.Actions>
</Modal> </Modal>
......
import {
Button,
Checkbox,
Form,
Header,
Icon,
Modal,
TextArea,
} from 'semantic-ui-react';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Modal, Button, Icon, Checkbox, Form, TextArea, Header } from 'semantic-ui-react'; import {
check,
clearWrite,
correctSolution,
getDocuments,
getSolutions,
selectSolution,
setchecktrue,
writeSolution,
} from '../../actions/homework';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { correctSolution, writeSolution, check } from '../../actions/homework';
class CorrectSolutionForm extends Component { class CorrectSolutionForm extends Component {
constructor(props) { constructor(props) {
...@@ -12,90 +30,131 @@ class CorrectSolutionForm extends Component { ...@@ -12,90 +30,131 @@ class CorrectSolutionForm extends Component {
} }
render() { render() {
const { const { studentFullName, studentId, taskTitle, taskSolutions } = this.props;
studentName, studentFullName, studentId, taskTitle, taskSolutions, const taskSolutionsProfile = taskSolutions.filter(
} = this.props; (solution) => solution.created_by === studentId
const taskSolutionsProfile = );
taskSolutions.filter(solution => solution.created_by === studentId); const relevantSolution = taskSolutionsProfile.slice(-1)[0];
const relevantSolution = taskSolutionsProfile[taskSolutionsProfile.length - 1]; const relevantDocuments = this.props.homeworks.documents
const relevantDocuments = this.props.homeworks.documents.filter(document => .filter((document) => document.solution === relevantSolution.id)
document.solution === relevantSolution.id).filter(document => .filter((document) => document.uploaded_by_name === studentFullName);
document.uploaded_by_name === studentFullName); const relevantDocument = relevantDocuments.slice(-1)[0];
const relevantDocument = relevantDocuments[relevantDocuments.length - 1];
let fileLink; let fileLink;
if (relevantDocument !== undefined || relevantDocument !== null) { if (relevantDocument && relevantDocument.file_url) {
fileLink = `/media${relevantDocument.file.split('media')[1]}`; fileLink = `${relevantDocument.file_url}`;
} else {
fileLink = null;
} }
const { corrected, accepted, note } = this.props.correction;
const { note } = this.props.correction;
return ( return (
<Modal <Modal
open={this.state.showModal} open={this.state.showModal}
closeOnDimmerClick
onClose={() => this.setState({ showModal: false })}
trigger={ trigger={
<Button <Button
inverted inverted
color='orange' color={this.props.color}
style={{ marginRight: '1.5em', marginTop: '1.5em' }} style={{ marginRight: '1.5em', marginTop: '1.5em' }}
onClick={() => { this.setState({ showModal: true }); }} onClick={() => {
this.setState({ showModal: true });
this.props.selectSolution(relevantSolution);
}}
> >
{studentName} {studentFullName}
</Button> </Button>
} }
> >
<Modal.Header> <Modal.Header>
A(z) {taskTitle} nevű feladat {studentName} által beadott megoldásának kijavítása: A(z) {taskTitle} nevű feladat {studentFullName} által beadott
megoldásának kijavítása:
</Modal.Header> </Modal.Header>
<Modal.Content> <Modal.Content>
<Header as='h5'>A megoldás leírása:</Header> <Header as="h5">A megoldás címe:</Header>
{relevantDocument === undefined ? 'Nincs leírás.' : relevantDocument.description.split('\n')} {relevantDocument && relevantDocument.description ? (
<Header as='h5'>A beadott dokumentum:</Header> <p>{relevantDocument.name}</p>
{relevantDocument === undefined ? ) : (
<p>Nincs fájl.</p> : <p>Nincs cím.</p>
<a href={fileLink}>Fájl letöltése</a>} )}
<Header as='h5'>Elfogadás/Elutasítás:</Header> <Header as="h5">A megoldás leírása:</Header>
<Button color={this.props.correction.accepted ? 'green' : 'red'} onClick={() => this.props.check()}> {relevantDocument && relevantDocument.description ? (
<Checkbox relevantDocument.description
label={this.props.correction.accepted .split('\n')
? 'Elfogadható' .map((s) => <p key={Math.random()}>{s}</p>)
: 'Nem elfogadható'} ) : (
checked={this.props.correction.accepted} <p>Nincs leírás.</p>
/> )}
<Header as="h5">A beadott dokumentum:</Header>
{fileLink ? (
<a href={fileLink} rel="noreferrer noopener" target>
Fájl letöltése
</a>
) : (
<p>Nincs fájl.</p>
)}
<Header as="h5">Kijavítás állapotának változtatása:</Header>
<Button
color="orange"
inverted={corrected}
onClick={() => this.props.check('corrected')}
>
<Checkbox label="Nincs kijavítva" checked={!corrected} />
</Button>
<Header as="h5">Elfogadás/elutasítás:</Header>
<Button
color="green"
inverted={!accepted}
onClick={() => {
this.props.check('accepted');
this.props.setchecktrue('corrected');
}}
>
<Checkbox label="Elfogadható" checked={accepted} />
</Button>
<Button
color="red"
inverted={accepted}
onClick={() => this.props.check('accepted')}
>
<Checkbox label="Nem elfogadható" checked={!accepted} />
</Button> </Button>
<Header as='h5'>Megjegyzés:</Header> <Header as="h5">A feladat megoldásának szöveges értékelése:</Header>
<Form> <Form>
<Form.Field <Form.Field
control={TextArea} control={TextArea}
name='note' name="note"
onChange={e => this.props.writeSolution(e)} onChange={(e) => this.props.writeSolution(e)}
value={note} value={note}
placeholder='Írhatsz megjegyzést a megoldásra...' placeholder="Írhatsz megjegyzést a megoldásra..."
/> />
</Form> </Form>
</Modal.Content> </Modal.Content>
<Modal.Actions> <Modal.Actions>
<Button <Button
inverted inverted
color='red' color="red"
onClick={() => { onClick={() => {
this.setState({ showModal: false }); this.setState({ showModal: false });
this.props.clearWrite();
}} }}
> >
<Icon name='remove' /> Mégse <Icon name="remove" /> Mégse
</Button> </Button>
<Button <Button
inverted inverted
color='green' color="green"
onClick={() => { onClick={() => {
this.props.correctSolution( this.props.correctSolution(
relevantSolution.id, relevantSolution.id,
true, corrected,
this.props.correction.accepted, accepted,
this.props.correction.note, note
); );
this.setState({ showModal: false }); this.setState({ showModal: false });
this.props.clearWrite();
}} }}
> >
<Icon name='checkmark' /> Beadás <Icon name="checkmark" /> Beadás
</Button> </Button>
</Modal.Actions> </Modal.Actions>
</Modal> </Modal>
...@@ -103,10 +162,19 @@ class CorrectSolutionForm extends Component { ...@@ -103,10 +162,19 @@ class CorrectSolutionForm extends Component {
} }
} }
const mapStateToProps = ({ homeworks, correction, user }) => ({ homeworks, correction, user }); const mapStateToProps = ({ homeworks, correction, user }) => ({
homeworks,
correction,
user,
});
export default connect(mapStateToProps, { export default connect(mapStateToProps, {
correctSolution, correctSolution,
writeSolution, writeSolution,
check, check,
setchecktrue,
clearWrite,
getSolutions,
getDocuments,
selectSolution,
})(CorrectSolutionForm); })(CorrectSolutionForm);
import { Button, Form, Icon, Input, Modal, TextArea } from 'semantic-ui-react';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Modal, Button, Form, Input, TextArea, Icon } from 'semantic-ui-react'; import { clearWrite, editNews, writeNews } from '../../actions/news';
import { connect } from 'react-redux';
import { writeNews, editNews, clearWrite } from '../../actions/news'; import { connect } from 'react-redux';
import moment from 'moment';
class EditNewsForm extends Component { class EditNewsForm extends Component {
constructor(props) { constructor(props) {
...@@ -13,8 +14,16 @@ class EditNewsForm extends Component { ...@@ -13,8 +14,16 @@ class EditNewsForm extends Component {
} }
render() { render() {
const { id, title, text } = this.props.selectedNews; const {
const editedBy = this.props.user.id; id,
title,
text,
author,
last_update_by,
created_at,
updated_at,
} = this.props.selectedNews;
const updated_by = this.props.user.id;
return ( return (
<Modal <Modal
open={this.state.showModal} open={this.state.showModal}
...@@ -22,8 +31,10 @@ class EditNewsForm extends Component { ...@@ -22,8 +31,10 @@ class EditNewsForm extends Component {
trigger={ trigger={
<Button <Button
compact compact
onClick={() => { this.setState({ showModal: true }); }} onClick={() => {
size='mini' this.setState({ showModal: true });
}}
size="mini"
> >
Edit Edit
</Button> </Button>
...@@ -31,45 +42,56 @@ class EditNewsForm extends Component { ...@@ -31,45 +42,56 @@ class EditNewsForm extends Component {
> >
<Modal.Header>Szerkesztés:</Modal.Header> <Modal.Header>Szerkesztés:</Modal.Header>
<Modal.Content> <Modal.Content>
<p style={{ fontStyle: 'italic' }}>
<b>Közzétéve:</b> {moment(created_at).format('LLLL')} <br />
<b>Írta:</b> {author} <br />
<b>Szerkesztve:</b> {moment(updated_at).format('LLLL')} <br />
<b>Szerkesztette:</b> {last_update_by}
</p>
<Form> <Form>
<Form.Field <Form.Field
control={Input} control={Input}
label='Title' label="Title"
name='title' name="title"
onChange={e => this.props.writeNews(e)} onChange={(e) => this.props.writeNews(e)}
value={title} value={title}
placeholder='Title' placeholder="Title"
/> />
<Form.Field <Form.Field
control={TextArea} control={TextArea}
label='Text' label="Text"
name='text' name="text"
onChange={e => this.props.writeNews(e)} onChange={(e) => this.props.writeNews(e)}
value={text} value={text}
placeholder='Tell us what you want...' placeholder="Tell us what you want..."
/> />
</Form> </Form>
</Modal.Content> </Modal.Content>
<Modal.Actions> <Modal.Actions>
<Button <Button
inverted inverted
color='red' color="red"
onClick={() => { this.setState({ showModal: false }); }} onClick={() => {
this.setState({ showModal: false });
}}
> >
<Icon name='remove' /> Cancel <Icon name="remove" /> Cancel
</Button> </Button>
<Button <Button
inverted inverted
color='green' color="green"
onClick={() => { onClick={() => {
this.props.editNews({ this.props.editNews({
id, title, text, editedBy, id,
}); title,
this.setState({ showModal: false }); text,
this.props.clearWrite(); updated_by,
}} });
this.setState({ showModal: false });
this.props.clearWrite();
}}
> >
<Icon name='checkmark' /> Edit <Icon name="checkmark" /> Edit
</Button> </Button>
</Modal.Actions> </Modal.Actions>
</Modal> </Modal>
...@@ -80,5 +102,7 @@ class EditNewsForm extends Component { ...@@ -80,5 +102,7 @@ class EditNewsForm extends Component {
const mapStateToProps = ({ user, selectedNews }) => ({ user, selectedNews }); const mapStateToProps = ({ user, selectedNews }) => ({ user, selectedNews });
export default connect(mapStateToProps, { export default connect(mapStateToProps, {
editNews, writeNews, clearWrite, editNews,
writeNews,
clearWrite,
})(EditNewsForm); })(EditNewsForm);
import { Button, Form, Icon, Input, Modal, TextArea } from 'semantic-ui-react';
import React, { Component } from 'react';
import {
clearWrite,
editTask,
writeTask,
writeTaskDeadline,
} from '../../actions/homework';
import { DateTimeInput } from 'semantic-ui-calendar-react';
import { connect } from 'react-redux';
import moment from 'moment';
class EditTaskForm extends Component {
constructor(props) {
super(props);
this.state = {
showModal: false,
};
}
render() {
const { id, title, text, deadline, bits } = this.props.selectedTask;
return (
<Modal
open={this.state.showModal}
onOpen={this.props.onClick}
closeOnDimmerClick
onClose={() => this.setState({ showModal: false })}
trigger={
<Button
inverted
style={{ marginRight: '2em' }}
color="orange"
onClick={() => {
this.setState({ showModal: true });
}}
>
<Icon name="edit" /> Módosítás
</Button>
}
>
<Modal.Header>A{title} nevű feladat módosítása:</Modal.Header>
<Modal.Content>
<Form>
<Form.Field
control={Input}
label="Cím:"
name="title"
onChange={(e) => this.props.writeTask(e)}
value={title}
placeholder="Add meg a feladat címét."
/>
<Form.Field
control={TextArea}
label="Leírás:"
name="text"
onChange={(e) => this.props.writeTask(e)}
value={text}
placeholder="Add meg a feladat leírását..."
/>
<Form.Field
control={DateTimeInput}
label="Beadási határidő (a jelenlegi időnél későbbi időpont):"
name="deadline"
placeholder="Beadási határidő"
iconPosition="left"
dateTimeFormat="YYYY-MM-DDTHH:mm"
onChange={(e, { name, value }) => {
this.props.writeTaskDeadline({ name, value });
}}
value={deadline}
/>
<Form.Field
control={Input}
type="number"
label="Bitek száma:"
name="bits"
onChange={(e) => this.props.writeTask(e)}
value={bits}
placeholder="Add meg a feladatért kapható bitek számát ..."
/>
</Form>
</Modal.Content>
<Modal.Actions>
<Button
inverted
color="red"
onClick={() => {
this.setState({ showModal: false });
this.props.clearWrite();
}}
>
<Icon name="remove" /> Mégse
</Button>
<Button
inverted
color="green"
disabled={
title === '' ||
(title !== undefined ? title.length > 150 : false) ||
text === '' ||
deadline === '' ||
moment().isAfter(deadline)
}
onClick={() => {
this.props.editTask({
id,
title,
text,
deadline,
bits,
});
this.setState({ showModal: false });
this.props.clearWrite();
}}
>
<Icon name="checkmark" /> Módosítás
</Button>
</Modal.Actions>
</Modal>
);
}
}
const mapStateToProps = ({ selectedTask, user }) => ({ selectedTask, user });
export default connect(mapStateToProps, {
writeTask,
writeTaskDeadline,
editTask,
clearWrite,
})(EditTaskForm);
#task,
#tasknote {
border: none;
background-color: inherit;
color: teal;
}
#tasknote {
color: black;
}
#task:hover,
#tasknote:hover {
color: red;
cursor: pointer;
}
import React, { Component } from 'react';
import { Segment } from 'semantic-ui-react';
class HiddenForm extends Component {
render() {
return (
<div>
<div style={{ marginBottom: 0, fontWeight: this.props.fontWeight }}>
{this.props.label}
</div>
<Segment style={{ marginTop: 0 }}>
<div>{this.props.value}</div>
</Segment>
</div>
);
}
}
export default HiddenForm;
import { Button, Header, Icon, Modal } from 'semantic-ui-react';
import React, { Component } from 'react';
class InfoModal extends Component {
constructor(props) {
super(props);
this.state = {
showModal: false,
};
}
close = () => this.setState({ showModal: false });
open = () => this.setState({ showModal: true });
render() {
const { button, title, content } = this.props;
const open = this.state.showModal;
return (
<Modal
open={open}
closeOnDimmerClick
trigger={button}
onOpen={this.open}
onClose={this.close}
size="small"
basic
>
<Header icon="info" content={title} />
<Modal.Content>
{content.split('\n').map((s) => (
<p key={Math.random()}>{s}</p>
))}
</Modal.Content>
<Modal.Actions>
<Button color="green" inverted onClick={() => this.close()}>
<Icon name="checkmark" /> Rendben
</Button>
</Modal.Actions>
</Modal>
);
}
}
export default InfoModal;
import './Forms.css';
import { Button, Divider, Header, Icon, Modal } from 'semantic-ui-react';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Modal, Button, Header, Icon } from 'semantic-ui-react'; import { getDocuments, getSolutions } from '../../actions/homework';
import { connect } from 'react-redux';
import CorrectSolutionForm from './CorrectSolutionForm'; import CorrectSolutionForm from './CorrectSolutionForm';
import { emptyMessage } from '../pages/Homework'; import { connect } from 'react-redux';
import { customMessage } from '../pages/Homework';
class SolutionDetailsForm extends Component { class SolutionDetailsForm extends Component {
constructor(props) { constructor(props) {
...@@ -13,89 +17,143 @@ class SolutionDetailsForm extends Component { ...@@ -13,89 +17,143 @@ class SolutionDetailsForm extends Component {
} }
render() { render() {
const taskSolutions = this.props.homeworks.solutions.filter(solution => const taskSolutions = this.props.homeworks.solutions.filter(
solution.task === this.props.taskid); (solution) => solution.task === this.props.taskid
);
const noSubmitStudents = []; const noSubmitStudents = [];
const waitForCorrectionStudents = []; const waitForCorrectionStudents = [];
const noAcceptStudents = []; const noAcceptStudents = [];
const acceptedStudents = []; const acceptedStudents = [];
for (let i = 0; i < this.props.homeworks.profiles.length; i += 1) { this.props.homeworks.profiles.forEach((profile) => {
const profileSolutions = taskSolutions.filter(solution => const profileSolutions = taskSolutions.filter(
solution.created_by === this.props.homeworks.profiles[i].id); (solution) => solution.created_by === profile.id
);
if (profileSolutions.length === 0) { if (profile.role === 'Student') {
noSubmitStudents.push(this.props.homeworks.profiles[i]); if (profileSolutions.length === 0) {
} else if (taskSolutions[taskSolutions.length - 1].corrected === false) { noSubmitStudents.push(profile);
waitForCorrectionStudents.push(this.props.homeworks.profiles[i]); } else if (
} else if (taskSolutions[taskSolutions.length - 1].accepted === false) { profileSolutions[profileSolutions.length - 1].corrected === false
noAcceptStudents.push(this.props.homeworks.profiles[i]); ) {
} else { waitForCorrectionStudents.push(profile);
acceptedStudents.push(this.props.homeworks.profiles[i]); } else if (
profileSolutions[profileSolutions.length - 1].accepted === false
) {
noAcceptStudents.push(profile);
} else {
acceptedStudents.push(profile);
}
} }
} });
const emptyStudentText = 'Nincs ilyen képződő jelenleg.'; const noStudentText = 'Nincs ilyen képződő jelenleg.';
return ( return (
<Modal <Modal
open={this.state.showModal} open={this.state.showModal}
closeOnDimmerClick
onClose={() => this.setState({ showModal: false })}
trigger={ trigger={
<Button basic color='blue' onClick={() => { this.setState({ showModal: true }); }}> <button
<Icon name='external' /> type="button"
id="task"
onClick={() => {
this.setState({ showModal: true });
this.props.getSolutions();
this.props.getDocuments();
}}
>
<Icon name="external" />
{this.props.tasktitle} {this.props.tasktitle}
</Button> </button>
} }
> >
<Modal.Header> <Modal.Header>
A megoldások beadásának állapota a(z) {this.props.tasktitle} nevű feladatnál: A megoldások beadásának állapota a(z) {this.props.tasktitle} nevű
feladatnál:
</Modal.Header> </Modal.Header>
<Modal.Content> <Modal.Content>
<Header as='h3'>Nem érkezett még megoldás:</Header> <Header as="h3">A feladat leírása:</Header>
{noSubmitStudents.length === 0 ? {this.props.taskdesc.split('\n').map((s) => (
emptyMessage(emptyStudentText) : <p key={Math.random()}>{s}</p>
noSubmitStudents.map(student => ( ))}
<Button color='blue' style={{ marginRight: '1.5em', marginTop: '1.5em' }}>{student.nick}</Button> <Divider />
)) <Header as="h3">Nem érkezett még megoldás:</Header>
} {noSubmitStudents.length === 0
<Header as='h3'>Javításra vár (A névre kattintva kijavítható a megoldás):</Header> ? customMessage(noStudentText)
{waitForCorrectionStudents.length === 0 ? : noSubmitStudents.map((student) => (
emptyMessage(emptyStudentText) : <Button
waitForCorrectionStudents.map(student => ( key={Math.random()}
<CorrectSolutionForm color="blue"
studentName={student.nick} style={{ marginRight: '1.5em', marginTop: '1.5em' }}
studentFullName={student.full_name} >
studentId={student.id} {student.full_name}
taskTitle={this.props.tasktitle} </Button>
taskSolutions={taskSolutions} ))}
/> <Divider />
)) <Header as="h3">
} Javításra vár (A névre kattintva kijavítható a megoldás):
<Header as='h3'>A megoldás nem elfogadható:</Header> </Header>
{noAcceptStudents.length === 0 ? {waitForCorrectionStudents.length === 0
emptyMessage(emptyStudentText) : ? customMessage(noStudentText)
noAcceptStudents.map(student => ( : waitForCorrectionStudents.map((student) => (
<Button color='red' style={{ marginRight: '1.5em', marginTop: '1.5em' }}>{student.nick}</Button> <CorrectSolutionForm
)) key={Math.random()}
} color="orange"
<Header as='h3'>Elfogadva:</Header> studentName={student.nick}
{acceptedStudents.length === 0 ? studentFullName={student.full_name}
emptyMessage(emptyStudentText) : studentId={student.id}
acceptedStudents.map(student => ( taskTitle={this.props.tasktitle}
<Button color='green' style={{ marginRight: '1.5em', marginTop: '1.5em' }}>{student.nick}</Button> taskSolutions={taskSolutions}
)) />
} ))}
<Divider />
<Header as="h3">
A megoldás nem elfogadható (A névre kattintva módosítható a
javítás):
</Header>
{noAcceptStudents.length === 0
? customMessage(noStudentText)
: noAcceptStudents.map((student) => (
<CorrectSolutionForm
key={Math.random()}
color="red"
studentName={student.nick}
studentFullName={student.full_name}
studentId={student.id}
taskTitle={this.props.tasktitle}
taskSolutions={taskSolutions}
/>
))}
<Divider />
<Header as="h3">
Elfogadva (A névre kattintva módosítható a javítás):
</Header>
{acceptedStudents.length === 0
? customMessage(noStudentText)
: acceptedStudents.map((student) => (
<CorrectSolutionForm
key={Math.random()}
color="green"
studentName={student.nick}
studentFullName={student.full_name}
studentId={student.id}
taskTitle={this.props.tasktitle}
taskSolutions={taskSolutions}
/>
))}
</Modal.Content> </Modal.Content>
<Modal.Actions> <Modal.Actions>
<Button <Button
inverted inverted
color='green' color="green"
onClick={() => { onClick={() => {
this.setState({ showModal: false }); this.setState({ showModal: false });
}} }}
> >
<Icon name='checkmark' /> Kész <Icon name="checkmark" /> Kész
</Button> </Button>
</Modal.Actions> </Modal.Actions>
</Modal> </Modal>
...@@ -106,4 +164,6 @@ class SolutionDetailsForm extends Component { ...@@ -106,4 +164,6 @@ class SolutionDetailsForm extends Component {
const mapStateToProps = ({ homeworks, user }) => ({ homeworks, user }); const mapStateToProps = ({ homeworks, user }) => ({ homeworks, user });
export default connect(mapStateToProps, { export default connect(mapStateToProps, {
getSolutions,
getDocuments,
})(SolutionDetailsForm); })(SolutionDetailsForm);
src/components/images/kszk_with_shadow.png

251 KiB