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
Select Git revision
  • 2023-ujoncdelutan
  • 2023-update
  • master
  • 1.0
  • 1.0.1
  • 1.0.10
  • 1.0.12
  • 1.0.13
  • 1.0.14
  • 1.0.15
  • 1.0.16
  • 1.0.17
  • 1.0.18
  • 1.0.19
  • 1.0.2
  • 1.0.3
  • 1.0.4
  • 1.0.5
  • 1.0.6
  • 1.0.7
  • 1.0.8
  • 1.0.9
  • 1.1.0
  • 1.1.1
  • 1.1.2
  • 1.1.3
  • 1.1.4
  • 1.1.5
  • 1.2.0
  • 1.3.0
  • 1.3.1
  • 1.3.10
  • 1.3.11
  • 1.3.12
  • 1.3.13
  • 1.3.14
  • 1.3.15
  • 1.3.16
  • 1.3.17
  • 1.3.18
  • 1.3.19
  • 1.3.2
  • 1.3.3
  • 1.3.4
  • 1.3.5
  • 1.3.6
  • 1.3.7
  • 1.3.8
  • 1.3.9
  • 1.4.0
  • 1.4.1
  • 1.4.2
  • 1.4.3
  • 1.4.4
  • 1.4.5
  • 1.4.6
  • 1.4.7
57 results

Target

Select target project
  • kszk/devteam/kszkepzes/old/kszkepzes-frontend
  • kbgergely/kszkepzes-frontend
2 results
Select Git revision
  • master
  • 1.0
  • 1.0.1
  • 1.0.10
  • 1.0.12
  • 1.0.13
  • 1.0.14
  • 1.0.15
  • 1.0.16
  • 1.0.17
  • 1.0.18
  • 1.0.19
  • 1.0.2
  • 1.0.3
  • 1.0.4
  • 1.0.5
  • 1.0.6
  • 1.0.7
  • 1.0.8
  • 1.0.9
  • 1.1.0
  • 1.1.1
  • 1.1.2
  • 1.1.3
  • 1.1.4
  • 1.1.5
  • 1.2.0
  • 1.3.0
  • 1.3.1
29 results
Show changes
Showing
with 1616 additions and 1058 deletions
#task { #task,
#tasknote {
border: none; border: none;
background-color: inherit; background-color: inherit;
color: teal; color: teal;
} }
#task:hover { #tasknote {
color: black;
}
#task:hover,
#tasknote:hover {
color: red; color: red;
cursor: pointer; 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, Divider } 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 './Forms.css'; import { customMessage } from '../pages/Homework';
class SolutionDetailsForm extends Component { class SolutionDetailsForm extends Component {
constructor(props) { constructor(props) {
...@@ -14,97 +17,143 @@ class SolutionDetailsForm extends Component { ...@@ -14,97 +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 (this.props.homeworks.profiles[i].role === 'Student') { if (profile.role === 'Student') {
if (profileSolutions.length === 0) { if (profileSolutions.length === 0) {
noSubmitStudents.push(this.props.homeworks.profiles[i]); noSubmitStudents.push(profile);
} else if (taskSolutions[taskSolutions.length - 1].corrected === false) { } else if (
waitForCorrectionStudents.push(this.props.homeworks.profiles[i]); profileSolutions[profileSolutions.length - 1].corrected === false
} else if (taskSolutions[taskSolutions.length - 1].accepted === false) { ) {
noAcceptStudents.push(this.props.homeworks.profiles[i]); waitForCorrectionStudents.push(profile);
} else if (
profileSolutions[profileSolutions.length - 1].accepted === false
) {
noAcceptStudents.push(profile);
} else { } else {
acceptedStudents.push(this.props.homeworks.profiles[i]); 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 id='task' 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'>A feladat leírása:</Header> <Header as="h3">A feladat leírása:</Header>
{this.props.taskdesc.split('\n').map(s => (<p>{s}</p>))} {this.props.taskdesc.split('\n').map((s) => (
<p key={Math.random()}>{s}</p>
))}
<Divider /> <Divider />
<Header as='h3'>Nem érkezett még megoldás:</Header> <Header as="h3">Nem érkezett még megoldás:</Header>
{noSubmitStudents.length === 0 ? {noSubmitStudents.length === 0
emptyMessage(emptyStudentText) : ? customMessage(noStudentText)
noSubmitStudents.map(student => ( : noSubmitStudents.map((student) => (
<Button color='blue' style={{ marginRight: '1.5em', marginTop: '1.5em' }}>{student.full_name}</Button> <Button
)) key={Math.random()}
} color="blue"
style={{ marginRight: '1.5em', marginTop: '1.5em' }}
>
{student.full_name}
</Button>
))}
<Divider /> <Divider />
<Header as='h3'>Javításra vár (A névre kattintva kijavítható a megoldás):</Header> <Header as="h3">
{waitForCorrectionStudents.length === 0 ? Javításra vár (A névre kattintva kijavítható a megoldás):
emptyMessage(emptyStudentText) : </Header>
waitForCorrectionStudents.map(student => ( {waitForCorrectionStudents.length === 0
<CorrectSolutionForm ? customMessage(noStudentText)
studentName={student.nick} : waitForCorrectionStudents.map((student) => (
studentFullName={student.full_name} <CorrectSolutionForm
studentId={student.id} key={Math.random()}
taskTitle={this.props.tasktitle} color="orange"
taskSolutions={taskSolutions} studentName={student.nick}
/> studentFullName={student.full_name}
)) studentId={student.id}
} taskTitle={this.props.tasktitle}
taskSolutions={taskSolutions}
/>
))}
<Divider /> <Divider />
<Header as='h3'>A megoldás nem elfogadható:</Header> <Header as="h3">
{noAcceptStudents.length === 0 ? A megoldás nem elfogadható (A névre kattintva módosítható a
emptyMessage(emptyStudentText) : javítás):
noAcceptStudents.map(student => ( </Header>
<Button color='red' style={{ marginRight: '1.5em', marginTop: '1.5em' }}>{student.full_name}</Button> {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 /> <Divider />
<Header as='h3'>Elfogadva:</Header> <Header as="h3">
{acceptedStudents.length === 0 ? Elfogadva (A névre kattintva módosítható a javítás):
emptyMessage(emptyStudentText) : </Header>
acceptedStudents.map(student => ( {acceptedStudents.length === 0
<Button color='green' style={{ marginRight: '1.5em', marginTop: '1.5em' }}>{student.full_name}</Button> ? 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>
...@@ -115,4 +164,6 @@ class SolutionDetailsForm extends Component { ...@@ -115,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

import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import {
Menu,
Container,
Button,
Segment,
Visibility,
Responsive,
} from 'semantic-ui-react';
const FixedMenu = ({ user, menuItems }) => (
<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 DesktopContainer extends Component {
constructor(props) {
super(props);
this.state = {
visible: false,
};
}
componentWillMount() {
this.props.getUserData();
}
hideFixedMenu() {
this.setState({ visible: false });
}
showFixedMenu() {
this.setState({ visible: true });
}
render() {
const { visible } = this.state;
const { children, user, menuItems } = this.props;
return (
<Responsive minWidth={768}>
{visible ? <FixedMenu user={this.props.user} menuItems={menuItems} /> : null}
<Visibility
onBottomPassed={() => this.showFixedMenu()}
onBottomVisible={() => this.hideFixedMenu()}
once={false}
>
<Segment inverted textAlign='center' vertical>
<Container>
<Menu inverted secondary stackable size='large'>
{menuItems.map((item, i) =>
(this.props.user.permission >= item.permissionLevel ||
(item.permissionLevel === 0) ?
<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>
</Container>
</Segment>
</Visibility>
{children}
</Responsive>
);
}
}
export default DesktopContainer;
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import {
Menu,
Container,
Button,
Segment,
Image,
Responsive,
Sidebar,
Icon,
} from 'semantic-ui-react';
import KSZKlogo from '../images/kszk_logo.svg';
class MobileContainer extends Component {
constructor(props) {
super(props);
this.state = {
sidebarVisible: false,
};
}
componentWillMount() {
this.props.getUserData();
}
render() {
const visible = this.state.sidebarVisible;
const { children, user, menuItems } = this.props;
return(
<Responsive maxWidth={767}>
<Segment inverted textAlign='center' vertical>
<Container>
<Menu inverted secondary>
<Menu.Item onClick={visible ? this.handleHideClick : this.handleShowClick}><Icon name='sidebar'/></Menu.Item>
<Image size='mini' src={KSZKlogo} style={{ marginRight: '1.5em' }} />
<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>
</Container>
</Segment>
<Sidebar.Pushable>
<Sidebar
as={Menu}
animation='overlay'
icon='labeled'
inverted
vertical
visible={visible}
width='thin'
>
{menuItems.map((item, i) =>
(this.props.user.permission >= item.permissionLevel ||
(item.permissionLevel === 0) ?
<Menu.Item key={i} as={Link} to={item.to} onClick={this.handleSidebarHide}>{item.text}</Menu.Item>
:
null))}
</Sidebar>
<Sidebar.Pusher onClick={this.handleSidebarHide}>
{children}
</Sidebar.Pusher>
</Sidebar.Pushable>
</Responsive>);
}
handleShowClick = () => this.setState({ sidebarVisible: true })
handleHideClick = () => this.setState({ sidebarVisible: false })
handleSidebarHide = () => this.setState({ sidebarVisible: false })
}
export default MobileContainer;
import { Button, Container, Header, Item, Label } from 'semantic-ui-react';
import React, { Component } from 'react'; import React, { Component } from 'react';
import {
Container,
Header,
Item,
Button,
Label,
List,
Form,
Comment,
} from 'semantic-ui-react';
import { connect } from 'react-redux';
import { getSelectedProfile, setStatus } from '../../actions/statistics'; import { getSelectedProfile, setStatus } from '../../actions/statistics';
import { getNotesByProfile, writeNote, clearWrite, postNote, deleteNote } from '../../actions/notes';
import ConfirmModal from '../forms/ConfirmModal';
import moment from 'moment'; import ConfirmModal from '../forms/ConfirmModal';
import { connect } from 'react-redux';
const options = [ const groupTypes = {
{ key: 'DT', text: 'DevTeam' }, HAT: {
{ key: 'NET', text: 'NETeam' }, name: 'Hallgatói Tudásbázis',
{ key: 'ST', text: 'SecurITeam' }, color: 'purple',
{ key: 'SYS', text: 'SysAdmin' }, },
{ key: 'HAT', text: 'Hallgatói Tudásbázis' }, SYS: {
]; name: 'Sysadmin',
color: 'violet',
},
NET: {
name: 'NETeam',
color: 'blue',
},
ST: {
name: 'SecurITeam',
color: 'teal',
},
DT: {
name: 'DevTeam',
color: 'green',
},
};
class ApplicantProfile extends Component { class ApplicantProfile extends Component {
componentWillMount() { UNSAFE_componentWillMount() {
this.props.getSelectedProfile(this.props.match.params.id); this.props.getSelectedProfile(this.props.match.params.id);
this.props.getNotesByProfile(this.props.match.params.id);
}
renderGroups() {
const { groups } = this.props.selectedProfile;
const groupNames = options.map(item => (groups.includes(item.key) ? item.text : null));
return groupNames.map(item => (
<List.Item>
<List.Content>
<List.Header>{item}</List.Header>
</List.Content>
</List.Item>
));
}
renderComments() {
const notes = this.props.profileNotes;
return notes.map((note) => {
if (!note.event) {
return (
<Comment>
<Comment.Content>
<Comment.Author>{note.created_by_name}</Comment.Author>
<Comment.Metadata>
{moment(note.created_at).format('LL')}
</Comment.Metadata>
<Comment.Text>
{note.note}
</Comment.Text>
</Comment.Content>
{ this.props.user.fullName === note.created_by_name ?
<ConfirmModal
text='törölni akarod a megjegyzést'
button={
<Button
compact
color='red'
size='mini'
>
Delete
</Button>
}
onAccept={() => this.props.deleteNote(note)}
/>
:
null }
</Comment>);
}
return '';
});
} }
render() { render() {
const note = this.props.actualNote; const {
const { id, signed, groups, role, full_name, nick, motivation_about, motivation_exercise, motivation_profession } id,
= this.props.selectedProfile; signed,
role,
full_name,
nick,
motivation_about,
motivation_exercise,
motivation_profession,
groups,
} = this.props.selectedProfile;
return ( return (
<Container style={{ padding: '60px' }}> <Container style={{ paddingTop: '3em', paddingBottom: '6em' }}>
<Item> <Item>
<Item.Content> <Item.Content>
<Container textAlign='center'> <Container textAlign="center" style={{ paddingBottom: '2em' }}>
<Header as='h2'>{full_name}</Header> <Header as="h2">{full_name}</Header>
<Item.Meta>{nick}</Item.Meta> <Item.Meta>{nick}</Item.Meta>
<Header as="h2">
{groups?.map((group) => (
<Label color={groupTypes[group].color}>
{groupTypes[group].name}
</Label>
))}
</Header>
</Container> </Container>
<Item.Description> <Item.Description>
<Container textAlign='justified' style={{ padding: '30px' }}> <Container textAlign="justified" style={{ padding: '1em' }}>
<Header as='h3'>Magamról, eddigi tevékenységem:</Header> <Header as="h3">Magamról, eddigi tevékenységem:</Header>
<p>{motivation_about}</p> <p>
<Header as='h3'>Szakmai motiváció:</Header> {motivation_about?.split('\n').map((item, i) => (
<p>{motivation_profession}</p> <div key={i}>{item}</div>
<Header as='h3'>Feladatok megoldása:</Header> ))}
<p>{motivation_exercise}</p> </p>
<Header as='h3'>Érdeklődés:</Header> <Header as="h3">Szakmai motiváció:</Header>
{ groups ? <p>
<List horizontal> {motivation_profession?.split('\n').map((item, i) => (
{this.renderGroups()} <div key={i}>{item}</div>
</List> ))}
: </p>
null <Header as="h3">Feladatok megoldása:</Header>
} <p>
{motivation_exercise?.split('\n').map((item, i) => (
<div key={i}>{item}</div>
))}
</p>
</Container> </Container>
<Container textAlign='center' style={{ padding: '20px' }}> <Container textAlign="center" style={{ padding: '1em' }}>
<Header as='h3'>Státusz:</Header> <Header as="h3">Státusz:</Header>
{ signed ? {signed ? (
<div> <div>
{ role === 'Student' ? {role === 'Student' ? (
<Label color='green' size='huge'>Elfogadva</Label> <Label color="green" size="huge">
: Elfogadva
null </Label>
} ) : null}
{ role === 'Staff' ? {role === 'Staff' ? (
<Label color='blue' size='huge'>Staff</Label> <Label color="blue" size="huge">
: Staff
null </Label>
} ) : null}
{ role === 'Applicant' ? {role === 'Applicant' ? (
<Label color='orange' size='huge'>Jelentkezett</Label> <Label color="orange" size="huge">
: Jelentkezett
null </Label>
} ) : null}
{ role === 'Denied' ? {role === 'Denied' ? (
<Label color='red' size='huge'>Elutasítva</Label> <Label color="red" size="huge">
: Elutasítva
null </Label>
} ) : null}
</div> </div>
: ) : (
<Label color='red' size='huge'>Nem jelentkezett</Label> <Label color="red" size="huge">
} Nem jelentkezett
</Label>
)}
</Container> </Container>
</Item.Description> </Item.Description>
</Item.Content> </Item.Content>
</Item> </Item>
{ signed && role !== 'Staff' ? {signed && role !== 'Staff' ? (
<Container> <Container textAlign="center">
<Container textAlign='center'> <ConfirmModal
<ConfirmModal button={<Button color="green">Jelentkezés elfogadása</Button>}
button={ text="elfogadod a jelentkezést"
<Button onAccept={() => this.props.setStatus(id, 'Student')}
color='green' />
>Jelentkezés elfogadása <ConfirmModal
</Button>} button={<Button color="red">Jelentkezés elutasítása</Button>}
text='elfogadod a jelentkezést' text="elutasítod a jelentkezést"
onAccept={() => this.props.setStatus(id, 'Student')} onAccept={() => this.props.setStatus(id, 'Denied')}
/> />
<ConfirmModal
button={
<Button
color='red'
>Jelentkezés elutasítása
</Button>}
text='elutasítod a jelentkezést'
onAccept={() => this.props.setStatus(id, 'Denied')}
/>
</Container>
<Comment.Group>
<Header dividing>
Megjegyzések
</Header>
{this.renderComments()}
<Form reply>
<Form.TextArea
value={note.note}
onChange={e => this.props.writeNote(e)}
/>
<Button
onClick={() => {
this.props.postNote({ userid: id,
note: note.note });
this.props.clearWrite();
}
}
content='Megjegyzés hozzáadása'
labelPosition='left'
icon='edit'
primary
/>
</Form>
</Comment.Group>
</Container> </Container>
: ) : null}
null
}
</Container> </Container>
); );
} }
} }
const mapStateToProps = ({ const mapStateToProps = ({ trainees: { selectedProfile } }) => ({
user, selectedProfile,
trainees: { selectedProfile }, });
notes: { profileNotes, actualNote }
}) => ({ user, selectedProfile, profileNotes, actualNote });
export default connect(mapStateToProps, { export default connect(mapStateToProps, { getSelectedProfile, setStatus })(
getSelectedProfile, ApplicantProfile
setStatus, );
postNote,
getNotesByProfile,
writeNote,
deleteNote,
clearWrite,
})(ApplicantProfile);
import { Button, Container, Label, Table } from 'semantic-ui-react';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { Container, Table, Label, Button } from 'semantic-ui-react';
import { connect } from 'react-redux';
import { getProfiles, setStatus } from '../../actions/statistics'; import { getProfiles, setStatus } from '../../actions/statistics';
import ConfirmModal from '../forms/ConfirmModal'; import ConfirmModal from '../forms/ConfirmModal';
import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
const role = [
{
role: 'Staff',
text: 'Staff',
color: 'blue',
},
{
role: 'Student',
text: 'Elfogadott',
color: 'green',
},
{
role: 'Applicant',
text: 'Jelentkezett',
color: 'orange',
},
{
role: 'Denied',
text: 'Elutasított',
color: 'red',
},
{
role: 'no',
text: 'Nem jelentkezett',
color: 'red',
},
];
class Applications extends Component { class Applications extends Component {
componentWillMount() { UNSAFE_componentWillMount() {
this.props.getProfiles(); this.props.getProfiles();
} }
renderApplicants() { renderApplicants(format) {
return this.props.profiles.map((profile) => return this.props.profiles.map((profile) =>
{ return ( profile.role === format.role &&
<Table.Row> (profile.signed === true || profile.role === 'Staff') ? (
<Table.Cell> <Table.Row key={profile.id}>
<Link to={`applicant/${profile.id}`}> <Table.Cell textAlign="center">
{profile.full_name} <Link to={`applicant/${profile.id}`}>{profile.full_name}</Link>
</Link>
</Table.Cell>
{ profile.signed ?
<Table.Cell textAlign='center'>
{ profile.role === 'Student' ?
<Label color='green'>Elfogadva</Label>
:
null
}
{ profile.role === 'Staff' ?
<Label color='blue'>Staff</Label>
:
null
}
{ profile.role === 'Applicant' ?
<Label color='orange'>Jelentkezett</Label>
:
null
}
{ profile.role === 'Denied' ?
<Label color='red'>Elutasítva</Label>
:
null
}
</Table.Cell> </Table.Cell>
: {format.role === 'Staff' ? null : (
<Table.Cell textAlign='center'> <Table.Cell textAlign="center">
{ profile.role === 'Staff' ? <ConfirmModal
<Label color='blue'>Staff</Label> button={
: <Button color="blue" size="tiny">
<Label color='red'>Nem jelentkezett</Label> ADD STAFF STATUS
} </Button>
}
text="staff jogot adsz neki"
onAccept={() => this.props.setStatus(profile.id, 'Staff')}
/>
</Table.Cell>
)}
</Table.Row>
) : null
);
}
renderNotApplicants(format) {
return this.props.profiles.map((profile) =>
profile.signed === false && profile.role !== 'Staff' ? (
<Table.Row key={profile.id}>
<Table.Cell textAlign="center">
<Link to={`applicant/${profile.id}`}>{profile.full_name}</Link>
</Table.Cell> </Table.Cell>
} {format.role === 'Staff' ? null : (
<Table.Cell> <Table.Cell textAlign="center">
{ profile.role !== 'Staff' ? <ConfirmModal
<ConfirmModal button={
button={<Button <Button color="blue" size="tiny">
color='blue' ADD STAFF STATUS
size='tiny' </Button>
> }
Staff jog adás text="staff jogot adsz neki"
</Button>} onAccept={() => this.props.setStatus(profile.id, 'Staff')}
text='staff jogot adsz neki' />
onAccept={() => this.props.setStatus(profile.id, 'Staff')} </Table.Cell>
/> )}
: </Table.Row>
null } ) : null
</Table.Cell> );
</Table.Row> }
renderTable(format) {
return (
<Table color="blue" unstackable celled selectable compact>
<Table.Header>
<Table.Row>
<Table.HeaderCell textAlign="center">
<Label color={format.color}>{format.text}</Label>
</Table.HeaderCell>
{format.role !== 'Staff' ? (
<Table.HeaderCell width={3} textAlign="center">
<Label color={null}>
{format.role === 'no'
? this.props.profiles.filter(
(profile) =>
profile.signed === false && profile.role !== 'Staff'
).length
: this.props.profiles.filter(
(profile) =>
profile.role === format.role &&
(profile.signed === true || profile.role === 'Staff')
).length}{' '}
</Label>
</Table.HeaderCell>
) : null}
</Table.Row>
</Table.Header>
<Table.Body>
{format.role === 'no'
? this.renderNotApplicants(format)
: this.renderApplicants(format)}
</Table.Body>
</Table>
); );
});
} }
render() { render() {
return ( return (
<Container <Container
textAlign='center' textAlign="center"
style={{ style={{ paddingTop: '1em', paddingBottom: '5em' }}
padding: '80px'
}}
> >
<Table color='blue' selectable compact> {this.renderTable(role[2])} {/* Applicant */}
<Table.Header> {this.renderTable(role[1])} {/* Student */}
<Table.Row> {this.renderTable(role[0])} {/* Staff */}
<Table.HeaderCell>Jelentkezettek</Table.HeaderCell> {this.renderTable(role[3])} {/* Denied */}
<Table.HeaderCell textAlign='center'>Jelentkezés státusza:</Table.HeaderCell> {this.renderTable(role[4])} {/* Not Signed */}
<Table.HeaderCell />
</Table.Row>
</Table.Header>
<Table.Body>
{this.renderApplicants()}
</Table.Body>
</Table>
</Container> </Container>
); );
} }
} }
const mapStateToProps = ({ trainees: { profiles }, user }) => ({ profiles, user }); const mapStateToProps = ({ trainees: { profiles }, user }) => ({
profiles,
user,
});
export default connect(mapStateToProps, { getProfiles, setStatus })(Applications); export default connect(mapStateToProps, { getProfiles, setStatus })(
Applications
);
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Button, Comment, Modal } from 'semantic-ui-react';
import { deleteNote } from '../../actions/notes';
import ConfirmModal from '../forms/ConfirmModal';
class CommentModal extends Component {
renderComments() {
const { notes, user } = this.props;
return notes.map((note) => {
return (
<Comment style={{ padding: '1em' }} stylekey={note.id}>
<Comment.Content>
<Comment.Author><strong>{note.created_by_name}</strong></Comment.Author>
<Comment.Text>
{note.note}
</Comment.Text>
{ note.created_by_name === user.fullName ?
<ConfirmModal
text='törölni akarod a megjegyzést'
button={
<Button
compact
color='red'
size='mini'
>
Delete
</Button>
}
onAccept={() => this.props.deleteNote(note)}
/>
:
null }
</Comment.Content>
</Comment>
);
});
}
render() {
return (
<Modal
closeIcon
trigger={
<Button icon='comment alternate outline' />
}
>
<Modal.Header>Megjegyzések:</Modal.Header>
<Modal.Content>
{this.renderComments()}
</Modal.Content>
</Modal>
);
}
}
const mapStateToProps = ({ user }) => ({ user });
export default connect(mapStateToProps, { deleteNote })(CommentModal);
import React, { Component } from 'react';
import { import {
Container,
Item,
Button, Button,
Comment, Comment,
Container,
Divider,
Form, Form,
Header, Header,
Item,
Segment,
Table, Table,
} from 'semantic-ui-react'; } from "semantic-ui-react";
import { connect } from 'react-redux'; import React, { Component } from "react";
import moment from 'moment'; import {
import { getEventById, getTrainees, visitorChange, submitVisitors } from '../../actions/statistics'; clearWrite,
import { getNotesByEvent, writeNote, clearWrite, postNote, deleteNote } from '../../actions/notes'; getNotesByEvent,
import TraineeTableRow from './TraineeTableRow'; postEventNote,
import ConfirmModal from '../forms/ConfirmModal'; writeNote,
} from "../../actions/notes";
import {
getEventById,
getTrainees,
submitVisitors,
visitorChange,
} from "../../actions/statistics";
import TraineeTableRow from "./EventDetailTableRow";
import { connect } from "react-redux";
import moment from "moment";
class EventDetail extends Component { class EventDetail extends Component {
constructor(props) { constructor(props) {
...@@ -23,39 +35,59 @@ class EventDetail extends Component { ...@@ -23,39 +35,59 @@ class EventDetail extends Component {
}; };
} }
componentWillMount() { UNSAFE_componentWillMount() {
this.props.getEventById(this.props.match.params.id); this.props.getEventById(this.props.match.params.id);
this.props.getTrainees(); this.props.getTrainees();
this.props.getNotesByEvent(this.props.match.params.id); this.props.getNotesByEvent(this.props.match.params.id);
} }
renderTrainees() { renderTrainees() {
const event = this.props.selectedEvent; const event = this.props.selectedEvent;
return this.props.trainees.map((item) => { return this.props.trainees
const notes = this.props.eventNotes.filter(note => note.profile === item.id); ?.sort(function (a, b) {
return ( var nameA = a.full_name.toLowerCase(),
<TraineeTableRow nameB = b.full_name.toLowerCase();
selectedEvent={event} if (nameA < nameB)
notes={notes} //sort string ascending
trainee={item} return -1;
edit={this.state.edit} if (nameA > nameB) return 1;
/> return 0; //default return value (no sorting)
); })
}); .map((item) => {
const notes = this.props.eventNotes?.filter(
(note) => note.profile === item.id
);
return item.role === "Student" ? (
<TraineeTableRow
selectedEvent={event}
notes={notes}
trainee={item}
edit={this.state.edit}
key={item.id}
/>
) : null;
});
} }
renderEvent() { renderEvent() {
const { name, date, description } = this.props.selectedEvent; const { name, date, description } = this.props.selectedEvent;
return ( return (
<Item> <Segment>
<Item.Header as='h2'>{name}</Item.Header> <Item>
<Item.Header as='h3'>Dátum: {moment(date).format('LL')}</Item.Header> <Divider style={{ fontSize: "2em" }} horizontal>
<Container textAlign='justified'> <Header as="h1">
<Item.Header as='h3'>Leírás</Item.Header> {name}
<Item.Content>{description}</Item.Content> <Item.Header style={{ fontSize: "0.6em" }}>
</Container> {moment(date).format("LL")}
</Item> </Item.Header>
</Header>
</Divider>
<Container textAlign="justified">
<Item.Header as="h3">Leírás</Item.Header>
<Item.Content>{description}</Item.Content>
</Container>
</Item>
</Segment>
); );
} }
...@@ -64,35 +96,20 @@ class EventDetail extends Component { ...@@ -64,35 +96,20 @@ class EventDetail extends Component {
return notes.map((note) => { return notes.map((note) => {
if (!note.profile) { if (!note.profile) {
return ( return (
<Comment> <Segment>
<Comment.Content> <Comment key={Math.random()}>
<Comment.Author>{note.created_by_name}</Comment.Author> <Comment.Content>
<Comment.Metadata> <Comment.Author>{note.created_by_name}</Comment.Author>
{moment(note.created_at).format('LL')} <Comment.Metadata>
</Comment.Metadata> {moment(note.created_at).format("LL")}
<Comment.Text> </Comment.Metadata>
{note.note} <Comment.Text>{note.note}</Comment.Text>
</Comment.Text> </Comment.Content>
</Comment.Content> </Comment>
{ this.props.user.fullName === note.created_by_name ? </Segment>
<ConfirmModal );
text='törölni akarod a megjegyzést'
button={
<Button
compact
color='red'
size='mini'
>
Delete
</Button>
}
onAccept={() => this.props.deleteNote(note)}
/>
:
null }
</Comment>);
} }
return ''; return "";
}); });
} }
...@@ -100,94 +117,76 @@ class EventDetail extends Component { ...@@ -100,94 +117,76 @@ class EventDetail extends Component {
const event = this.props.selectedEvent; const event = this.props.selectedEvent;
const note = this.props.actualNote; const note = this.props.actualNote;
return ( return (
<Container <Container style={{ paddingTop: "1em", paddingBottom: "7em" }}>
style={{ <Container textAlign="center">
padding: '80px' {this.props.selectedEvent && this.props.trainees
}} ? this.renderEvent()
> : ""}
<Container textAlign='center'>
{ this.props.selectedEvent && this.props.trainees ?
this.renderEvent()
:
''
}
</Container> </Container>
<Table centered> {!this.state.edit ? (
<Table.Header> <Button onClick={() => this.setState({ edit: true })}>
<Table.Row> Módosítás
<Table.HeaderCell>Név</Table.HeaderCell> </Button>
<Table.HeaderCell textAlign='center'>Jelen volt</Table.HeaderCell> ) : (
<Table.HeaderCell>Megjegyzések</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{ this.props.selectedEvent && this.props.trainees ?
this.renderTrainees()
:
''
}
</Table.Body>
</Table>
<Button <Button
inverted onClick={() => {
color='orange' this.setState({ edit: false });
onClick={() => this.setState({ edit: true })} }}
> >
Szerkeszt {" "}
Kész
</Button> </Button>
{ this.state.edit ? )}
<Table celled unstackable>
<Table.Header>
<Table.Row textAlign="center">
<Table.HeaderCell>Név</Table.HeaderCell>
<Table.HeaderCell>Jelen volt</Table.HeaderCell>
<Table.HeaderCell>Megjegyzések</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{this.props.selectedEvent ? this.renderTrainees() : null}
</Table.Body>
</Table>
<Comment.Group>
<Header dividing>Megjegyzések</Header>
{this.props.eventNotes ? this.renderComments() : ""}
<Form reply>
<Form.TextArea
value={note.note}
onChange={(e) => this.props.writeNote(e)}
/>
<Button <Button
inverted
color='blue'
onClick={() => { onClick={() => {
this.setState({ edit: false }); this.props.postEventNote({
this.props.submitVisitors(this.props.selectedEvent); eventid: event.id,
} note: note.note,
} });
>Mentés this.props.clearWrite();
</Button> }}
: content="Megjegyzés hozzáadása"
'' labelPosition="left"
} icon="edit"
<Comment.Group> primary
<Header dividing> />
Megjegyzések </Form>
</Header> </Comment.Group>
{this.props.eventNotes ?
this.renderComments()
:
''
}
<Form reply>
<Form.TextArea
value={note.note}
onChange={e => this.props.writeNote(e)}
/>
<Button
onClick={() => {
this.props.postNote({ eventid: event.id,
note: note.note });
this.props.clearWrite();
}
}
content='Megjegyzés hozzáadása'
labelPosition='left'
icon='edit'
primary
/>
</Form>
</Comment.Group>
</Container> </Container>
); );
} }
} }
const mapStateToProps = ({ const mapStateToProps = ({
user,
notes: { eventNotes, actualNote }, notes: { eventNotes, actualNote },
events: { selectedEvent }, events: { selectedEvent },
trainees: { trainees } trainees: { trainees },
}) => ({ user, eventNotes, selectedEvent, trainees, actualNote }); }) => ({
eventNotes,
selectedEvent,
trainees,
actualNote,
});
export default connect(mapStateToProps, { export default connect(mapStateToProps, {
getEventById, getEventById,
...@@ -197,6 +196,5 @@ export default connect(mapStateToProps, { ...@@ -197,6 +196,5 @@ export default connect(mapStateToProps, {
submitVisitors, submitVisitors,
writeNote, writeNote,
clearWrite, clearWrite,
postNote, postEventNote,
deleteNote,
})(EventDetail); })(EventDetail);
import {
Button,
Comment,
Dropdown,
Form,
Grid,
Icon,
Popup,
Table,
} from 'semantic-ui-react';
import React, { Component } from 'react';
import { clearWrite, postEventNote, writeNote } from '../../actions/notes';
import { submitVisitors, visitorChange } from '../../actions/statistics';
import { connect } from 'react-redux';
const visitStates = [
{
text: 'Igen',
value: 'Visitor',
},
{
text: 'Szólt h nem',
value: 'Absent',
},
{
text: 'Nem',
value: 'No',
},
];
class TraineeTableRow extends Component {
constructor(props) {
super(props);
this.state = {
showAddPopup: false,
showMorePopup: false,
};
}
// Hides and shows the Add and More popup
triggerAdd = () =>
this.setState({ ...this.state, showAddPopup: !this.state.showAddPopup });
triggerMore = () =>
this.setState({ ...this.state, showMorePopup: !this.state.showMorePopup });
render() {
const note = this.props.actualNote;
const { trainee, selectedEvent, notes } = this.props;
const isVisitor = selectedEvent.visitors.includes(trainee.id);
const isAbsent = selectedEvent.absent.includes(trainee.id);
let visitorStatusIcon;
let visitorStatusDropdown;
if (isVisitor) {
visitorStatusIcon = <Icon color="green" name="checkmark" />;
visitorStatusDropdown = 'Visitor';
} else if (isAbsent) {
visitorStatusIcon = <Icon color="orange" name="minus" />;
visitorStatusDropdown = 'Absent';
} else {
visitorStatusIcon = <Icon color="red" name="cancel" />;
visitorStatusDropdown = 'No';
}
return (
<Table.Row>
<Table.Cell textAlign="center">{trainee.full_name}</Table.Cell>
{/* Show and change Visitors status */}
{!this.props.edit ? (
<Table.Cell textAlign="center">{visitorStatusIcon}</Table.Cell>
) : (
<Table.Cell textAlign="center">
<Dropdown
defaultValue={visitorStatusDropdown}
selection
options={visitStates}
onChange={(_, v) => {
this.props.visitorChange({ id: trainee.id, value: v.value });
// Submit with error check
this.props
.submitVisitors(this.props.selectedEvent)
.then((value) => {
if (value === true) {
console.log('success');
} else {
console.log('error');
}
});
}}
/>
</Table.Cell>
)}
{/* Notes for trainees */}
<Table.Cell>
<Grid>
<Grid.Row>
{/* Note text */}
<Grid.Column floated="left" width={8}>
{notes.length > 0 ? (
<Comment>
<Comment.Content>
<Comment.Author>
<b>{notes[0].created_by_name}:</b>
</Comment.Author>
<Comment.Text style={{ wordWrap: 'break-word' }}>
{notes[0].note.length > 25
? notes[0].note.slice(0, 25).concat('...')
: notes[0].note}
</Comment.Text>
</Comment.Content>
</Comment>
) : null}
</Grid.Column>
{/* Note buttons */}
<Grid.Column floated="right" width={6} textAlign="right">
{notes.length > 0 ? (
<Popup
basic
open={this.state.showMorePopup}
trigger={
<Button
icon="comment alternate outline"
onClick={this.triggerMore}
/>
}
content={notes.map((oneNote) => (
<Comment.Content>
<Comment.Author>
<b>{oneNote.created_by_name}:</b>
</Comment.Author>
<Comment.Text>{oneNote.note}</Comment.Text>
</Comment.Content>
))}
/>
) : null}
<Popup
basic
trigger={<Button icon="plus" onClick={this.triggerAdd} />}
open={this.state.showAddPopup}
content={
<Form reply>
<Form.TextArea
value={note.note}
onChange={(e) => this.props.writeNote(e)}
/>
<Button
primary
onClick={() => {
this.triggerAdd();
this.props.postEventNote({
eventid: selectedEvent.id,
userid: trainee.id,
note: note.note,
});
this.props.clearWrite();
}}
content="Megjegyzés hozzáadása"
labelPosition="left"
icon="edit"
/>
</Form>
}
/>
</Grid.Column>
</Grid.Row>
</Grid>
</Table.Cell>
</Table.Row>
);
}
}
const mapStateToProps = ({ notes: { actualNote } }) => ({ actualNote });
export default connect(mapStateToProps, {
writeNote,
clearWrite,
postEventNote,
visitorChange,
submitVisitors,
})(TraineeTableRow);
import { Button, Container, Table } from 'semantic-ui-react';
import React, { Component } from 'react'; import React, { Component } from 'react';
import moment from 'moment'; import { deleteEvent, getStaffEvents } from '../../actions/statistics';
import AddEventForm from '../forms/AddEventForm';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { Container, Table, Button, Icon } from 'semantic-ui-react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { getStaffEvents, deleteEvent, selectEventForEdit } from '../../actions/statistics'; import moment from 'moment';
import AddEventForm from '../forms/AddEventForm';
import EditEventForm from '../forms/EditEventForm';
import ConfirmModal from '../forms/ConfirmModal';
class Events extends Component { class Events extends Component {
componentWillMount() { UNSAFE_componentWillMount() {
this.props.getStaffEvents(); this.props.getStaffEvents();
} }
renderEvents() { renderEvents() {
return this.props.events.map((event) => return this.props.events.map((event) => (
{ return ( <Table.Row key={event.id}>
<Table.Row> <Table.Cell textAlign="center">
<Table.Cell> <Link to={`events/${event.id}`}>{event.name}</Link>
<Link to={`events/${event.id}`}> </Table.Cell>
{event.name} <Table.Cell textAlign="center">
</Link> {moment(event.date).format('LL')}
</Table.Cell> </Table.Cell>
<Table.Cell>{moment(event.date).format('LL')}</Table.Cell> <Table.Cell textAlign="center">{event.visitor_number}</Table.Cell>
<Table.Cell>{event.visitor_number}</Table.Cell> <Table.Cell textAlign="center">
<Table.Cell textAlign='center'> <Button
<EditEventForm onClick={() => this.props.selectEventForEdit(event)} /> onClick={() => this.props.deleteEvent(event)}
<ConfirmModal color="red"
text={`törölni akarod a következő alkalmat:${event.name}`} compact
button={ size="small"
<Button >
inverted Törlés
color='red' </Button>
>
<Icon name='x' />
Törlés
</Button>
}
onAccept={() => this.props.deleteEvent(event)}
/>
</Table.Cell> </Table.Cell>
</Table.Row> </Table.Row>
); ));
});
} }
render() { render() {
return ( return (
<Container textAlign='center'> <Container textAlign="center">
<Table color='blue' selectable compact> <div style={{ overflowX: 'scroll' }}>
<Table.Header> <Table
<Table.Row> color="blue"
<Table.HeaderCell>Alkalom neve</Table.HeaderCell> unstackable
<Table.HeaderCell>Dátum</Table.HeaderCell> celled
<Table.HeaderCell>Jelen voltak</Table.HeaderCell> selectable
<Table.HeaderCell /> compact
</Table.Row> size="small"
</Table.Header> >
<Table.Header>
<Table.Body> <Table.Row>
{this.props.events ? this.renderEvents() : 'Nincs még alaklom beírva'} <Table.HeaderCell textAlign="center">
</Table.Body> Alkalom neve
</Table> </Table.HeaderCell>
<Table.HeaderCell textAlign="center">Dátum</Table.HeaderCell>
<Table.HeaderCell textAlign="center">
Jelen voltak
</Table.HeaderCell>
<Table.HeaderCell />
</Table.Row>
</Table.Header>
<Table.Body>
{this.props.events
? this.renderEvents()
: 'Nincs még alkalom beírva'}
</Table.Body>
</Table>
</div>
<br />
<AddEventForm /> <AddEventForm />
</Container> </Container>
); );
...@@ -70,4 +76,6 @@ class Events extends Component { ...@@ -70,4 +76,6 @@ class Events extends Component {
const mapStateToProps = ({ events: { events }, user }) => ({ events, user }); const mapStateToProps = ({ events: { events }, user }) => ({ events, user });
export default connect(mapStateToProps, { getStaffEvents, selectEventForEdit, deleteEvent })(Events); export default connect(mapStateToProps, { getStaffEvents, deleteEvent })(
Events
);
import React, { Component } from 'react';
import { Container, Header, Segment, Divider } from 'semantic-ui-react';
import './Groups.css'; import './Groups.css';
export default class Groups extends Component { import { Container, Header, Segment } from 'semantic-ui-react';
render() { import React, { Component } from 'react';
return (
<div>
<Segment style={{ padding: '8em 0em' }} vertical>
<Container text>
<Header as='h3' style={{ fontSize: '2em' }}>DevTeam</Header>
<p className='paragraph'>
A DevTeam a KSZK fejlesztő köre. Az informatika számos területével foglalkoznak, többek között például alkalmazás- és mobilszoftver fejlesztéssel, weblapkészítéssel. Ezen felül találkozhatsz mikrokontrollerek programozásával, legyen az akár Raspberry Pi vagy Arduino. Saját ötleteid megvalósításában is szívesen nyújtanak segítő kezet, illetve egyes gyűléseiken gyorstalpalókat tartanak, hogy az érdeklődők mielőbb be tudjanak csatlakozni a munkába.
</p>
<p className='paragraph'>
Jelenlegi projektjeik közé tartozik egy Schönherz szintű kölcsönzési rendszer kialakítása, egy gyakorlóoldal készítése, melyen egyetemi tárgyak ZH-ira, vizsgáira lehet készülni, a tanuló helyiségek foglaltságát vizsgáló rendszer bevezetése, de szívesen viszik érdeklődő, lelkes tagjaik új projektötleteit is.
</p>
<p className='paragraph'>
A kör szeretettel vár mindenkit, legyen akár profi fejlesztő, vagy olyan, aki csak most ismerkedik a fejlesztés szépségeivel náluk mindenki talál a képességeinek megfelelő elfoglaltságot.
</p>
<Divider as='h4' className='header' style={{ margin: '3em 0em' }} />
<Header as='h3' style={{ fontSize: '2em' }}>Hallgatói Tudásbázis</Header>
<p className='paragraph'>
A HaT (Hallgatói Tudásbázis) a VIK Wiki adminisztrációjáért, illetve üzemeltetéséért, fejlesztéséért felelős kör. Nekik köszönhető a Wiki rendezett állapota. Odafigyelnek , hogy kövessék a szerkesztői szokásokat, és rendszeresen felmérik, milyen újításra van kereslet. Azoknak a jelentkezését várják, akik nem riadnak vissza egy (rosszabb napjain) napi ötezer oldalmegtekintést produkáló rendszer ápolgatásától.
</p>
<Divider as='h4' className='header' style={{ margin: '3em 0em' }} /> import GroupCard from '../extra/GroupCard';
<Header as='h3' style={{ fontSize: '2em' }}>NETeam</Header> import { connect } from 'react-redux';
<p className='paragraph'> import { getGroups } from '../../actions/groups';
A NETeam foglalkozik a kollégiumi hálózati infrastruktúra üzemeltetésével és fejlesztésével. Biztosítják a hálózat folyamatos működését, követik az új hálózati technológiák alakulását, igyekeznek gyakorlatban is kipróbálni őket, alkalomadtán pedig cégekkel kapcsolatot tartva vesznek részt új megoldások tesztelésében is.
</p>
<p className='paragraph'>
A Schönherzben a 90-es évek óta üzemelteti a Házat lefedő hálózatot a KSZK, mely azóta többször teljes cserén esett át. A KSZK reszorttá válása előtt a NETeam egy erre szakosodott csoportja volt, 2014 óta pedig önálló körként folytatja tevékenységét. A kör tagjai hagyományosan a NetAdmin és segéd-NetAdminok, akik a kollégiumi hálózat fenntartásáért felelősek, illetve a Netikai Bizottság elnöke és tagjai, akik a hálózathasználati szabályzatot tartatják be, illetve a hálózathasználati szabályzattal szemben elkövetett kihágásokat felügyelik és szankcionálják.
</p>
<p className='paragraph'>
Az ide kerülőknek lehetőségük van bekapcsolódni az ISO/OSI modell majdnem minden rétegében működő szolgáltatások üzemeltetésébe és fejlesztésébe, amit szolgáltatástól függően akár az egész karon használnak. Ilyen például a Cisco eszközök konfigurációja, WiFi hálózat, VoIP, VPN, DNS/Dinamikus DNS üzemeltetése, fejlesztése, felhasználói adatbázis kezelése, forgalommonitorozás. Ezek széleskörű rálátást engednek egy komplex hálózatra és a használt technológiák működésére. A használt hálózattól függetlenül kialakított router laborban pedig lehetőség van szinte bármilyen, az iparban használt switching/routing megoldás próba szintű felépítésére.
</p>
<p className='paragraph'>
Jelenleg várható legnagyobb projektjük a Házat teljes egészében lefedő WiFi hálózat kiépítése lesz, de a következő évben kilátásban van a Software Defined Networking megoldásokkal való ismerkedés, illetve a router labor továbbfejlesztése is.
</p>
<p className='paragraph'>
Aki csatlakozik a körbe és hálózatot vagy szolgáltatásokat üzemeltet, fejleszt, felelősséggel fog tartozni az általa irányított rendszerért, ezzel pedig fontos része lesz a Schönherzes közéletnek. Ez a felelősség, az ezzel járó nem kizárólag szakmai tapasztalat és technikai tudás pedig egy későbbi önéletrajzban is olyan tényező tud lenni, amivel kevés frissen végzett hálózati szakember rendelkezik.
</p>
<Divider as='h4' className='header' style={{ margin: '3em 0em' }} /> class Groups extends Component {
<Header as='h3' style={{ fontSize: '2em' }}>SecurITeam</Header> UNSAFE_componentWillMount() {
<p className='paragraph'> this.props.getGroups();
A SecurITeam-ben te is megismerkedhetsz az IT biztonságban használt technikákkal: weboldalakat, szervereket, zárakat és még hardvereket is törnek. }
</p>
<p className='paragraph'>
Csináltál egy weboldalt vagy appot, de nem vagy meggyőződve arról, hogy biztonságos? Náluk mind a támadó, mind a védekező oldal technikáiról tanulhatsz, és ki is próbálhatod a tudásodat élőben. Az SQL injection, programok visszafejtése és exploitálása, webes alkalmazások biztonságának vizsgálata, ismert támadások (pl. Shellshock, Meltdown) kipróbálása, gyenge titkosítások megkerülése, valamint a privacy védelme mind olyan dolgok, amivel ez a kör foglalkozik. A szoftveres témák mellett a fizikai biztonságra is hangsúlyt fektetnek, legyen az Bluetooth sniffing, rádiós lehallgatás, RFID klónozás vagy lockpicking, náluk megtalálod ez ehhez szükséges eszközöket és szaktudást!
</p>
<p className='paragraph'>
A kör előadásokat, tanfolyamokat és workshopokattart, illetve a Schönherzes infrastruktúra biztonságát rendszeresen pentestekkel ellenőrzik.
</p>
<p className='paragraph'>
A körben lehetőséged adódik arra, hogy a korábban felsorolt tevékenységek bármelyikével foglalkozz, tanulj, versenyezz IT biztonsági versenyeken (CTF), illetve a Wargame fejlesztésébe is be tudsz csatlakozni.
</p>
<Divider as='h4' className='header' style={{ margin: '3em 0em' }} /> render() {
<Header as='h3' style={{ fontSize: '2em' }}>Sysadmin</Header> return (
<p className='paragraph'> <div>
A Sysadmin a Schönherz szerverüzemeltetésével foglalkozó öntevékeny köre. A kollégiumban működő IT szolgáltatásokat nyújtó infrastruktúrát ők felügyelik, fejlesztik. Az általuk használt szoftverek között megtalálhatóak Linux, BSD, Solaris valamint Windows alapú megoldások is. Az infrastruktúra VPN szerverének segítségével akár otthonról is hozzáférhetsz azokhoz az erőforrásokhoz, amelyek csak az egyetemi hálózatból elérhetők. 2014 végén indult a legfiatalabb, RemoteApp névre hallgató szolgáltatásuk, mellyel úgy értheted el az oktatásban is használt (és egyéb) szoftvereket, hogy nem szükséges azokat telepítened a gépedre. A felhasználói igények alapján folyamatosan bővítik szolgáltatásaik palettáját. <Segment inverted textAlign="center" vertical>
</p> <Container>
<p className='paragraph'> <Header
Minden félévben indítanak új projekteket. Jelenleg és a következő félévekben egy Docker (Kubernetes) alapú container cluster fejlesztésén és üzembe helyezésén, illetve konfiguráció menedzsment bevezetésén dolgoznak. Az új dolgok mellett persze komoly hangsúlyt fektetnek a jelenleg üzemelő szerverek folyamatos karbantartására is. Náluk megtanulhatod, hogyan kell egy több fizikai hosztból álló, körülbelül 150 virtuális szervert kiszolgáló virtualizációs clustert üzemeltetni, de akár a webhosting területén is fejlesztheted tudásod a Ház legnagyobb (~200 weboldat kiszolgáló) szerverének felügyelete során. Ha szeretnél a felszín mögé látni, és releváns szakmai tapasztalatot szerezni a területen, akkor köztük a helyed. Az előismeret nem követelmény, a lelkesedés igen. as="h1"
</p> content="Köreink"
inverted
style={{
fontSize: '3em',
fontWeight: 'normal',
marginBottom: 0,
marginTop: '0.5em',
}}
/>
</Container>
</Segment>
<Segment style={{ padding: '1em 0em 5em' }} vertical>
<Container text>
{this.props.groups
// eslint-disable-next-line arrow-body-style
.map((item) => {
return (
<GroupCard
key={item.id}
label={item.name}
value={item.description}
/>
);
})}
</Container> </Container>
</Segment> </Segment>
</div> </div>
); );
} }
} }
const mapStateToProps = ({ groups }) => ({ groups });
export default connect(mapStateToProps, { getGroups })(Groups);
...@@ -5,9 +5,33 @@ ...@@ -5,9 +5,33 @@
.car-text-kszk { .car-text-kszk {
position: absolute; position: absolute;
width: 100%; width: 100%;
top: 0px; top: 1vw;
text-shadow: black 0px 0px 10px, black 0px 0px 6px;
-webkit-text-fill-color: white; -webkit-text-fill-color: white;
-webkit-text-stroke-color: black; }
/*-webkit-text-stroke-width: 0.1vw;*/
text-shadow: 2px 2px 2px black; .quote {
position: relative;
margin-bottom: 0.5rem;
}
.quote:before {
content: '“';
position: absolute;
left: -0.45em;
}
.quote::after {
content: '”';
margin-right: -1rem;
}
.quote--container {
margin: 2rem auto 0;
padding-bottom: 0.7rem;
}
.quote--author {
text-align: right;
font-weight: 300;
} }
import React, { Component } from 'react'; import "./Home.css";
import { import {
Button, Button,
Container, Container,
Divider,
Header, Header,
Icon, Icon,
Segment,
Image, Image,
Divider, Responsive,
} from 'semantic-ui-react'; Segment,
import { connect } from 'react-redux'; } from "semantic-ui-react";
import Slider from 'react-slick'; /* eslint-disable react/jsx-props-no-spreading */
import { Link } from 'react-router-dom'; import React, { Component } from "react";
import './Home.css';
import KSZKbiglogo from '../images/kszk_big_logo.png'; import KSZKbiglogo from "../images/kszk_with_shadow.png";
import { Link } from "react-router-dom";
import Slider from "react-slick";
import { connect } from "react-redux";
import { getImages } from "../../actions/home";
const settings = { const settings = {
dots: false, dots: false,
...@@ -25,184 +30,393 @@ const settings = { ...@@ -25,184 +30,393 @@ const settings = {
slidesToScroll: 1, slidesToScroll: 1,
centerMode: true, centerMode: true,
lazyLoad: true, lazyLoad: true,
initialSlide: Math.floor((Math.random() * 32) + 1), initialSlide: Math.floor(Math.random() * 32 + 1),
}; };
const range = (count) => { class Home extends Component {
const newArray = []; UNSAFE_componentWillMount() {
for (let i = 1; i < count; i += 1) { this.props.getImages();
newArray.push(i);
} }
return newArray; renderSlider(view, imageWidth) {
}; if (view === 0) {
return (
class Home extends Component { <div>
render() { {!!this.props.images}
return (
<div>
<div className='car-image-kszk'>
<Slider {...settings}> <Slider {...settings}>
{ {this.props.images &&
range(32).map(image => ( this.props.images.map((image) => (
<div key={image}> <div key={image}>
<img src={`images/${image}.jpg`} width='100%' alt='' /> <img src={image.image} width={imageWidth} alt="" />
</div> </div>
)) ))}
} </Slider>
<div className="car-text-kszk">
<Segment textAlign="center" vertical>
<Header
as="h1"
content="Üdvözlünk a"
inverted
style={{
fontSize: "3vw",
fontWeight: "normal",
marginBottom: 0,
}}
/>
<Header
as="h1"
content="Kollégiumi Számítástechnikai Kör"
inverted
style={{
fontSize: "3.5vw",
fontWeight: "bold",
marginBottom: "0.5vw",
marginTop: "0.5vw",
}}
/>
<Header
as="h1"
content="újoncképzésének weboldalán!"
inverted
style={{
fontSize: "3vw",
fontWeight: "normal",
marginBottom: 0,
marginTop: "0.5vw",
}}
/>
<Image
verticalAlign="middle"
src={KSZKbiglogo}
style={{ marginTop: "1vw", width: "17%" }}
/>
<Header
as="h1"
content="Szeretettel várunk a KSZKépzésre!"
inverted
style={{
fontSize: "3vw",
fontWeight: "normal",
marginBottom: 0,
marginTop: "1vw",
}}
/>
<Container>
{this.props.user.id ? (
<Button
as={Link}
to="/profile"
primary
size="huge"
style={{
fontSize: "2vw",
marginTop: "1vw",
marginBottom: "1vw",
fontWeight: "bold",
letterSpacing: "0.13vw",
}}
>
Jelentkezés
<Icon name="right arrow" />
</Button>
) : (
<Button
href="/oidc/authenticate/"
primary
size="huge"
style={{
fontSize: "2vw",
marginTop: "1vw",
marginBottom: "1vw",
fontWeight: "bold",
letterSpacing: "0.13vw",
}}
>
Bejelentkezés
<Icon name="right arrow" />
</Button>
)}
</Container>
</Segment>
</div>
</div>
);
}
if (view === 1) {
return (
<div>
<Slider {...settings}>
{this.props.images.map((image) => (
<div key={image}>
<img src={image.image} width={imageWidth} alt="" />
</div>
))}
</Slider> </Slider>
<div className='car-text-kszk'> <div className="car-text-kszk">
<Segment textAlign='center' vertical> <Segment textAlign="center" vertical>
<Header <Header
as='h1' as="h1"
content='Üdvözlünk a' content="Üdvözlünk a"
inverted inverted
style={{ style={{
fontSize: '2vw', fontSize: "5vw",
fontWeight: 'normal', fontWeight: "bold",
marginBottom: 0, marginBottom: 0,
marginTop: '0.5vw',
}} }}
/> />
<Header <Header
as='h1' as="h1"
content='Kollégiumi Számítástechnikai Kör' content="Kollégiumi Számítástechnikai Kör"
inverted inverted
style={{ style={{
fontSize: '3vw', fontSize: "6vw",
fontWeight: 'bold', fontWeight: "bold",
marginBottom: '0.5vw', marginBottom: "0.5vw",
marginTop: '0.5vw', marginTop: "0.5vw",
}} }}
/> />
<Header <Header
as='h1' as="h1"
content='újoncképzésének weboldalán!' content="újoncképzésének weboldalán!"
inverted inverted
style={{ style={{
fontSize: '2vw', fontSize: "5vw",
fontWeight: 'normal', fontWeight: "bold",
marginBottom: 0, marginBottom: 0,
marginTop: '0.5vw', marginTop: "0.5vw",
}} }}
/> />
<Image <Image
verticalAlign='middle' className="kszklogo"
verticalAlign="middle"
src={KSZKbiglogo} src={KSZKbiglogo}
style={{ marginTop: '2vw', width: '12%' }} style={{ marginTop: "1vw", width: "20%" }}
/> />
<Header <Header
as='h1' as="h1"
content='Szeretettel várunk a KSZKépzésre!' content="Szeretettel várunk a KSZKépzésre!"
inverted inverted
style={{ style={{
fontSize: '2vw', fontSize: "5vw",
fontWeight: 'normal', fontWeight: "bold",
marginBottom: 0, marginBottom: 0,
marginTop: '1vw', marginTop: "1vw",
}} }}
/> />
<Container> <Container>
{ {this.props.user.id ? (
this.props.user.id ? <Button
<Button as={Link}
as={Link} to="/profile"
to='/profile' primary
primary size="massive"
size='huge' style={{
style={{ fontSize: "4vw",
fontSize: '2vw', marginTop: "1.5vw",
marginTop: '1vw', marginBottom: "1vw",
marginBottom: '1vw', fontWeight: "bold",
}} letterSpacing: "0.15vw",
> }}
Jelentkezés >
<Icon name='right arrow' /> Jelentkezés
</Button> <Icon name="right arrow" />
: </Button>
<Button ) : (
href='/api/v1/login/authsch/' <Button
primary href="/oidc/authenticate/"
size='huge' primary
style={{ size="massive"
fontSize: '2vw', style={{
marginTop: '1vw', fontSize: "4vw",
marginBottom: '1vw', marginTop: "1vw",
}} marginBottom: "1vw",
> fontWeight: "bold",
Jelentkezés letterSpacing: "0.15vw",
<Icon name='right arrow' /> }}
</Button> >
} Bejelentkezés
<Icon name="right arrow" />
</Button>
)}
</Container> </Container>
</Segment> </Segment>
</div> </div>
</div> </div>
<Segment style={{ padding: '8em 0em', fontFamily: 'Arial' }} vertical> );
<Container text> }
<Header as='h3' style={{ fontSize: '2em', fontFamily: 'Arial' }}> }
Kik is vagyunk mi?
// eslint-disable-next-line class-methods-use-this
renderText() {
const kszk_age = new Date().getFullYear() - 1976;
return (
<Segment style={{ padding: "1em 0em", fontFamily: "Arial" }} vertical>
<Container text>
<Segment inverted color="green" tertiary>
<Header as="h3" style={{ fontSize: "2em", fontFamily: "Arial" }}>
Bemutatkozó videók
</Header> </Header>
<p style={{ fontSize: '1.33em', fontFamily: 'Arial' }}> <p style={{ fontSize: "1.33em", fontFamily: "Arial" }}>
A Kollégiumi Számítástechnikai Kör az Egyetem legrégebben működő A gólyakörtére készített videóinkat megnézhetitek a{" "}
és legnagyobb aktív, informatikával foglalkozó öntevékeny <a
csoportosulása, idén ünnepeljük 43. születésnapunkat. A patinás href="https://www.youtube.com/@kollegiumiszamitastechnika470/videos"
név mögött vidám hangulatú, alkotó kedvű csapat rejlik, mely a Kar target="_blank"
szakmai képességű, számítástechnika iránt kiemelten érdeklődő rel="noopener noreferrer"
tagjaiból verbuválódott, és bővül évente új tehetségekkel, lelkes style={{ color: "white", textDecoration: "underline" }}
informatikusokkal, villamosmérnökökkel. >
YouTube csatornánkon
</a>
!
</p> </p>
<Button as={Link} size='large' to='/groups'> </Segment>
Ismerd meg a köreinket! <Icon name='right arrow' /> <Header as="h3" style={{ fontSize: "2em", fontFamily: "Arial" }}>
</Button> Kik is vagyunk mi?
<Divider as='h4' className='header' style={{ margin: '3em 0em' }} /> </Header>
<Header as='h3' style={{ fontSize: '2em', fontFamily: 'Arial' }}> <p style={{ fontSize: "1.33em", fontFamily: "Arial" }}>
Lehetőségek A Kollégiumi Számítástechnikai Kör az Egyetem legrégebben működő és
</Header> legnagyobb aktív, informatikával foglalkozó öntevékeny
<p style={{ fontSize: '1.33em', fontFamily: 'Arial' }}> csoportosulása, idén ünnepeljük {kszk_age}. születésnapunkat. A
A KSZK a lehetőségek tárháza, a hely ahol Te leendő mérnök patinás név mögött vidám hangulatú, alkotó kedvű csapat rejlik, mely
minden területen kipróbálhatod, továbbképezheted magad. Nálunk a Kar szakmai képességű, számítástechnika iránt kiemelten
kibontakoztathatod kreativitásod, tapasztalatot, mérnöki érdeklődő tagjaiból verbuválódott, és bővül évente új tehetségekkel,
szemléletet szerezhetsz, miközben az ún. soft skill-jeidet is lelkes informatikusokkal, villamosmérnökökkel.
fejlesztheted. Ha számodra a szakma hivatás, ha szeretsz új </p>
dolgokat alkotni vagy csak társaságra vágysz, a legjobb helyre <Button as={Link} size="large" to="/groups">
kerültél. A reszort körei a szakma egy-egy meghatározó területével Ismerd meg a köreinket! <Icon name="right arrow" />
foglalkoznak a fejlesztés és üzemeltetés területén. </Button>
<Divider as="h4" className="header" style={{ margin: "3em 0em" }} />
<Header as="h3" style={{ fontSize: "2em", fontFamily: "Arial" }}>
Lehetőségek
</Header>
<p style={{ fontSize: "1.33em", fontFamily: "Arial" }}>
A KSZK a lehetőségek tárháza, a hely ahol Te leendő mérnök
minden területen kipróbálhatod, továbbképezheted magad. Nálunk
kibontakoztathatod kreativitásod, tapasztalatot, mérnöki szemléletet
szerezhetsz, miközben az ún. soft skill-jeidet is fejlesztheted. Ha
számodra a szakma hivatás, ha szeretsz új dolgokat alkotni vagy csak
társaságra vágysz, a legjobb helyre kerültél. A reszort körei a
szakma egy-egy meghatározó területével foglalkoznak a fejlesztés és
üzemeltetés területén.
</p>
<Divider as="h4" className="header" style={{ margin: "3em 0em" }} />
<Header as="h3" style={{ fontSize: "2em", fontFamily: "Arial" }}>
Miért KSZK-snak lenni?
</Header>
<div
class="quote--container"
style={{ fontSize: "1.5em", fontFamily: "Arial" }}
>
<p class="quote">
Szerintem KSZK-snak lenni, mert rengeteget tanulok belőle.
Gyakorlok, hallok újdonságokat, kipróbálhatom magam mindenféle
szerepben, és közben még barátokat is szerzek. Ezek a barátságok,
tapasztalatok egyébként később is nagyon jól jönnek, például a
CV-mben egész erős fegyvertény, hogy ennyi mindent csináltam.
Tényleg rengeteget kaptam a reszorttól, szakmailag és emberileg
is. Ja, és szeretem, hogy a KSZK ilyen szabad, és abba kóstolok
bele, amibe akarok.
</p>
<p class="quote--author">&ndash; Feri</p>
</div>
<div
class="quote--container"
style={{ fontSize: "1.5em", fontFamily: "Arial" }}
>
<p class="quote">
A nulláról kezdtem a képzést és az egyetemi tanulmányaimat is,
semmilyen infós tudásom nem volt, de rengeteget fejlődtem a
KSZK-nak köszönhetően. Ezenkívül nem csak szakmai tudást
szereztem, hanem egy fantasztikus közösség részévé is váltam.
</p>
<p class="quote--author">&ndash; Patrik</p>
</div>
<div
class="quote--container"
style={{ fontSize: "1.5em", fontFamily: "Arial" }}
>
<p class="quote">
Amikor idejöttem egyetemre nem tudtam, hogy mennyire fogom
megtalálni a helyem. Aztán, elkezdtem megismerkedni a kari
közösséggel és barátokat szereztem, akik jelentős részét a
KSZK-ban ismertem meg, vagy velem csatlakozott ide. Együtt
foglalkozgatunk projektekkel, a Ház rendszereinek üzemeltetésével
és egyéb nagyon érdekes ügyes-bajos dolgokkal. Úgy érzem, hogy a
KSZK-ban igazán megtaláltam a helyem, mind emberileg, mind
szakmailag.
</p> </p>
<Divider as='h4' className='header' style={{ margin: '3em 0em' }} /> <p class="quote--author">&ndash; Mike</p>
<Header as='h3' style={{ fontSize: '2em', fontFamily: 'Arial' }}> </div>
Képzésünk <div
class="quote--container"
style={{ fontSize: "1.5em", fontFamily: "Arial" }}
>
<p class="quote">
Számtalan dologgal foglalkozunk, és tényleg azt csinálhatom, ami
csak érdekel. Emellett a KSZK-t a szívügyemnek tekintem, szerintem
a legjobb lehetőség a szakmai fejlődésen kívül életre szóló
barátságok alakítására.
</p>
<p class="quote--author">&ndash; Blint</p>
</div>
<Divider as="h4" className="header" style={{ margin: "3em 0em" }} />
<Header as="h3" style={{ fontSize: "2em", fontFamily: "Arial" }}>
Képzésünk
</Header>
<p style={{ fontSize: "1.33em", fontFamily: "Arial" }}>
Képzésünk végén Te is igazi KSZK-ssá válhatsz, hiszen rengeteg
szakmai tudást igyekszünk átadni nektek. A képzésalkalmak rendkívül
hangulatban telnek, és a szociális irányultságú foglalkozások
alatt egy nagyon csapat kovácsolódik az érdeklődőkből. Az első
képzés időpontja február 20. csütörtök 18:00, ettől kezdve pedig
minden héten egy közösségi és számos szakmai alkalom során
találkozunk. A képzésalkalmak után április 11-től 13-ig rendezünk
tábort. Az közösségi alkalmakon és a táboron kötelező a részvétel.
</p>
<Divider as="h4" className="header" style={{ margin: "3em 0em" }} />
<Segment inverted color="red" tertiary>
<Header as="h3" style={{ fontSize: "2em", fontFamily: "Arial" }}>
Korlátos férőhely
</Header> </Header>
<p style={{ fontSize: '1.33em', fontFamily: 'Arial' }}> <p style={{ fontSize: "1.33em", fontFamily: "Arial" }}>
Kilenc alkalmas képzésünk végén Te is igazi KSZK-ssá válhatsz, hiszen rengeteg szakmai tudást igyekszünk átadni nektek. A képzésalkalmak rendkívül hangulatban telnek, és a szociális irányultságú foglalkozások alatt egy nagyon csapat kovácsolódik az érdeklődőkből. Az első képzés időpontja február 17. vasárnap 18:50, ettől kezdve pedig minden héten találkozunk ugyanabban az időpontban. A képzés ideje alatt egy teljes hétvégés tábort is rendezünk majd (ennek időpontját az Újoncdélutánig tisztázzuk). Az alkalmakon és a táboron kötelező a részvétel. Általánosságban elmondható, hogy a KSZK tagjai rengeteg dologgal
foglalkoznak a hétköznapjaik során, hogy minden informatikai
rendszer úgy működjön a kollégiumban, ahogy kell. Így van ez
velünk képzőkkel is, emiatt a férőhelyek korlátosak.
</p> </p>
<Divider as='h4' className='header' style={{ margin: '3em 0em' }} /> <p style={{ fontSize: "1.33em", fontFamily: "Arial" }}>
<Segment inverted color='red' tertiary> Sajnos előfordulhat olyan eset, hogy valaki már nem fér be a
<Header as='h3' style={{ fontSize: '2em', fontFamily: 'Arial' }}> képzésre, ezért kérünk titeket, hogy ennek tudatában
Korlátos férőhely jelentkezzetek majd. Ilyen esetben reméljük ez nem szegi
</Header> kedveteket és jövőre újra próbálkoztok majd!
<p style={{ fontSize: '1.33em', fontFamily: 'Arial' }}> </p>
Általánosságban elmondható, hogy a KSZK tagjai rengeteg dologgal foglalkoznak </Segment>
a hétköznapjaik során, hogy minden informatikai rendszer úgy működjön </Container>
a kollégiumban, ahogy kell. Így van ez velünk képzőkkel is, emiatt </Segment>
hetente csak egy képzésalkalmat tudunk tartani. Mivel az oktatóterem );
férőhelyében korlátozott, ezért a képzésre maximum 35 embert tudunk befogadni. }
</p>
<p style={{ fontSize: '1.33em', fontFamily: 'Arial' }}> render() {
Sajnos előfordulhat olyan eset, hogy valaki már nem fér be a képzésre, return (
ezért kérünk titeket, hogy ennek tudatában jelentkezzetek majd. <div>
Ilyen esetben reméljük ez nem szegi kedveteket és jövőre újra próbálkoztok majd! <Responsive minWidth={600}>
</p> <div className="car-image-kszk">
</Segment> <div />
</Container> {this.renderSlider(0, "120%")}
</Segment> </div>
{this.renderText()}
</Responsive>
<Responsive maxWidth={600}>
<div className="car-image-kszk">{this.renderSlider(1, "200%")}</div>
{this.renderText()}
</Responsive>
</div> </div>
); );
} }
} }
const mapStateToProps = ({ user }) => ({ const mapStateToProps = ({ user, images }) => ({
user, user,
images,
}); });
export default connect(mapStateToProps, {})(Home); export default connect(mapStateToProps, { getImages })(Home);
import React, { Component } from 'react';
import { import {
Button,
Container, Container,
Header, Header,
Segment,
Table,
Icon, Icon,
Label,
Message, Message,
Button, Segment,
Table,
} from 'semantic-ui-react'; } from 'semantic-ui-react';
import { connect } from 'react-redux'; /* eslint-disable no-nested-ternary */
import moment from 'moment'; import React, { Component } from 'react';
import { import {
getTasks,
getSolutions,
addTask, addTask,
setSelectedTask,
deleteTask, deleteTask,
addDocument,
getProfiles,
getDocuments, getDocuments,
getProfiles,
getSolutions,
getTasks,
setSelectedTask,
} from '../../actions/homework'; } from '../../actions/homework';
import AddTaskForm from '../forms/AddTaskForm';
import AddSolutionForm from '../forms/AddSolutionForm'; import AddSolutionForm from '../forms/AddSolutionForm';
import SolutionDetailsForm from '../forms/SolutionDetailsForm'; import AddTaskForm from '../forms/AddTaskForm';
import EditTaskForm from '../forms/EditTaskForm';
import ConfirmModal from '../forms/ConfirmModal'; import ConfirmModal from '../forms/ConfirmModal';
import EditTaskForm from '../forms/EditTaskForm';
import InfoModal from '../forms/InfoModal';
import SolutionDetailsForm from '../forms/SolutionDetailsForm';
import { connect } from 'react-redux';
import moment from 'moment';
// Display type for the Table Semantic UI component
// {icon} {text} - Displayed for the student for each Task
// {rowstyle} - Table row style (red text, yellow bg, ...)
const displayTypes = { const displayTypes = {
can_submit: { can_submit: {
text: 'Beadható', text: 'Beadható',
...@@ -54,7 +60,7 @@ const displayTypes = { ...@@ -54,7 +60,7 @@ const displayTypes = {
}, },
}; };
export const emptyMessage = (header, text, marginBottom, warning) => ( export const customMessage = (header, text, marginBottom, warning) => (
<Message <Message
style={{ marginBottom }} style={{ marginBottom }}
icon={warning ? 'warning' : 'info'} icon={warning ? 'warning' : 'info'}
...@@ -68,18 +74,18 @@ export const emptyMessage = (header, text, marginBottom, warning) => ( ...@@ -68,18 +74,18 @@ export const emptyMessage = (header, text, marginBottom, warning) => (
class Homework extends Component { class Homework extends Component {
componentDidMount() { componentDidMount() {
this.props.getTasks(); this.props.getTasks();
this.props.getSolutions(this.props.user.id);
this.props.getProfiles(); this.props.getProfiles();
this.props.getSolutions();
this.props.getDocuments(); this.props.getDocuments();
} }
// Returns a table style for the given task
getTaskDisplayStyle(task) { getTaskDisplayStyle(task) {
const taskSolutions = this.props.homeworks.solutions.filter(solution => const taskSolution = this.props.homeworks.solutions.filter(
solution.task === task.id) (solution) => solution.task === task.id
.filter(solution => );
solution.created_by === this.props.user.id);
if (taskSolutions.length === 0) { if (taskSolution.length === 0) {
if (moment().isBefore(task.deadline)) { if (moment().isBefore(task.deadline)) {
return 'can_submit'; return 'can_submit';
} }
...@@ -87,34 +93,44 @@ class Homework extends Component { ...@@ -87,34 +93,44 @@ class Homework extends Component {
return 'no_submit'; return 'no_submit';
} }
if (taskSolutions[taskSolutions.length - 1].corrected === false) { if (taskSolution[0].corrected === false) {
return 'wait_correction'; return 'wait_correction';
} }
if (taskSolutions[taskSolutions.length - 1].accepted === false) { if (taskSolution[0].accepted === false) {
return 'no_accept'; return 'no_accept';
} }
return 'accepted'; return 'accepted';
} }
// Returns table rows for the tasks
// given parameters separates the active/inactive tasks and normal/staff users
renderTaskList(active, staff) { renderTaskList(active, staff) {
const { user, homeworks } = this.props;
const profileSolutions = homeworks.solutions.filter(
(solution) => solution.created_by === user.id
);
// Normal user
if (!staff) { if (!staff) {
return this.props.homeworks.tasks return homeworks.tasks
.filter(task => moment().isBefore(task.deadline) === active) .filter((task) => moment().isBefore(task.deadline) === active)
.map(task => ( .map((task) => (
// Style
<Table.Row <Table.Row
key={task.id} key={task.id}
warning={ warning={
displayTypes[this.getTaskDisplayStyle(task)].rowstyle.warning displayTypes[this.getTaskDisplayStyle(task)].rowstyle.warning
} }
positive={ positive={
displayTypes[this.getTaskDisplayStyle(task)].rowstyle.positive displayTypes[this.getTaskDisplayStyle(task)].rowstyle.positive
} }
negative={ negative={
displayTypes[this.getTaskDisplayStyle(task)].rowstyle.negative displayTypes[this.getTaskDisplayStyle(task)].rowstyle.negative
} }
> >
{/* Form component */}
<Table.Cell> <Table.Cell>
<AddSolutionForm <AddSolutionForm
taskid={task.id} taskid={task.id}
...@@ -124,53 +140,109 @@ class Homework extends Component { ...@@ -124,53 +140,109 @@ class Homework extends Component {
disabled={moment().isAfter(task.deadline)} disabled={moment().isAfter(task.deadline)}
/> />
</Table.Cell> </Table.Cell>
{/* Deadline Date */}
<Table.Cell> <Table.Cell>
{moment(task.deadline).format('YYYY. MM. DD. HH:mm')} {moment(task.deadline).format('YYYY. MM. DD. HH:mm')}
</Table.Cell> </Table.Cell>
<Table.Cell>
<Label
color={
displayTypes[this.getTaskDisplayStyle(task)].rowstyle.positive
? 'green'
: moment().isAfter(task.deadline)
? 'red'
: displayTypes[this.getTaskDisplayStyle(task)].rowstyle
.negative
? 'red'
: null
}
>
{task.bits} bit
</Label>
</Table.Cell>
{/* Status (Javításra vár, ...) */}
<Table.Cell> <Table.Cell>
<Icon name={displayTypes[this.getTaskDisplayStyle(task)].icon} />{' '} <Icon name={displayTypes[this.getTaskDisplayStyle(task)].icon} />{' '}
{displayTypes[this.getTaskDisplayStyle(task)].text} {displayTypes[this.getTaskDisplayStyle(task)].text}
{profileSolutions.filter(
(solution) => solution.task === task.id
) &&
profileSolutions
.filter((solution) => solution.task === task.id)
.slice(-1)[0] &&
profileSolutions
.filter((solution) => solution.task === task.id)
.slice(-1)[0].note ? (
<div>
<InfoModal
button={
<button type="button" id="tasknote">
(Megjegyzés <Icon name="external" />)
</button>
}
title="Megjegyzés a feladathoz"
content={
profileSolutions
.filter((solution) => solution.task === task.id)
.slice(-1)[0].note
}
onAccept={() => {}}
/>
</div>
) : (
''
)}
</Table.Cell> </Table.Cell>
</Table.Row> </Table.Row>
)); ));
} }
// Staff
const deleteButton = ( const deleteButton = (
<Button <Button inverted style={{ marginRight: '2em' }} color="red">
inverted <Icon name="x" /> Törlés
style={{ marginRight: '2em' }}
color='red'
>
<Icon name='x' /> Törlés
</Button> </Button>
); );
return this.props.homeworks.tasks return this.props.homeworks.tasks
.filter(task => moment().isBefore(task.deadline) === active) .filter((task) => moment().isBefore(task.deadline) === active)
.map(task => ( .map((task) => (
<Table.Row <Table.Row
key={task.id} key={task.id}
warning={ warning={
displayTypes[this.getTaskDisplayStyle(task)].rowstyle.warning displayTypes[this.getTaskDisplayStyle(task)].rowstyle.warning
} }
positive={ positive={
displayTypes[this.getTaskDisplayStyle(task)].rowstyle.positive displayTypes[this.getTaskDisplayStyle(task)].rowstyle.positive
} }
negative={ negative={
displayTypes[this.getTaskDisplayStyle(task)].rowstyle.negative displayTypes[this.getTaskDisplayStyle(task)].rowstyle.negative
} }
> >
{/* Form */}
<Table.Cell> <Table.Cell>
<SolutionDetailsForm taskid={task.id} tasktitle={task.title} taskdesc={task.text} /> <SolutionDetailsForm
taskid={task.id}
tasktitle={task.title}
taskdesc={task.text}
/>
</Table.Cell> </Table.Cell>
{/* Deadline Date */}
<Table.Cell> <Table.Cell>
{moment(task.deadline).format('YYYY. MM. DD. HH:mm')} {moment(task.deadline).format('YYYY. MM. DD. HH:mm')}
</Table.Cell> </Table.Cell>
{/* Bits */}
<Table.Cell>
<Label color={null}>{task.bits} bit</Label>
</Table.Cell>
{/* Admin buttons */}
<Table.Cell> <Table.Cell>
<EditTaskForm onClick={() => this.props.setSelectedTask(task)} /> <EditTaskForm onClick={() => this.props.setSelectedTask(task)} />
<ConfirmModal <ConfirmModal
button={deleteButton} button={deleteButton}
text='törlöd a kiválaszott feladatot a már beadott megoldásokkal együtt' text="törlöd a kiválaszott feladatot a már beadott megoldásokkal együtt"
onAccept={() => this.props.deleteTask(task)} onAccept={() => this.props.deleteTask(task)}
/> />
</Table.Cell> </Table.Cell>
...@@ -178,6 +250,7 @@ class Homework extends Component { ...@@ -178,6 +250,7 @@ class Homework extends Component {
)); ));
} }
// Active/Inactive tasks table
renderHomeworksTable(active, staff) { renderHomeworksTable(active, staff) {
let tableColor = 'green'; let tableColor = 'green';
let marginBottom = '0em'; let marginBottom = '0em';
...@@ -193,16 +266,17 @@ class Homework extends Component { ...@@ -193,16 +266,17 @@ class Homework extends Component {
<Table.Header> <Table.Header>
<Table.Row> <Table.Row>
<Table.HeaderCell> <Table.HeaderCell>
<Icon circular name='home' /> <Icon circular name="home" />
Feladat megnevezése / beadása Feladat megnevezése / beadása
</Table.HeaderCell> </Table.HeaderCell>
<Table.HeaderCell> <Table.HeaderCell>
<Icon circular name='calendar' /> <Icon circular name="calendar" />
Beadási határidő Beadási határidő
</Table.HeaderCell> </Table.HeaderCell>
<Table.HeaderCell width={2}></Table.HeaderCell>
<Table.HeaderCell> <Table.HeaderCell>
<Icon circular name='tasks' /> <Icon circular name="tasks" />
Állapot Állapot
</Table.HeaderCell> </Table.HeaderCell>
</Table.Row> </Table.Row>
</Table.Header> </Table.Header>
...@@ -215,15 +289,16 @@ class Homework extends Component { ...@@ -215,15 +289,16 @@ class Homework extends Component {
<Table.Header> <Table.Header>
<Table.Row> <Table.Row>
<Table.HeaderCell> <Table.HeaderCell>
<Icon circular name='home' /> <Icon circular name="home" />
Feladat megnevezése / Beadások állapota Feladat megnevezése / Beadások állapota
</Table.HeaderCell> </Table.HeaderCell>
<Table.HeaderCell> <Table.HeaderCell>
<Icon circular name='calendar' /> <Icon circular name="calendar" />
Beadási határidő Beadási határidő
</Table.HeaderCell> </Table.HeaderCell>
<Table.HeaderCell width={2}></Table.HeaderCell>
<Table.HeaderCell> <Table.HeaderCell>
<Icon circular name='edit' /> <Icon circular name="edit" />
Módosítás / Törlés Módosítás / Törlés
</Table.HeaderCell> </Table.HeaderCell>
</Table.Row> </Table.Row>
...@@ -233,11 +308,12 @@ class Homework extends Component { ...@@ -233,11 +308,12 @@ class Homework extends Component {
); );
} }
// Headers and stuff around the Tables
renderHomeworks(active, staff) { renderHomeworks(active, staff) {
let empty = false; let noTask = false;
let emptyText = 'Jelenleg nincs egyetlen beadható feladat sem. '; let noTaskText = 'Jelenleg nincs egyetlen beadható feladat sem. ';
let marginBottom = '0em'; let marginBottom = '0em';
const emptyHeaderText = 'Nincs feladat.'; const noTaskHeaderText = 'Nincs feladat.';
let headerText = 'Aktív feladatok'; let headerText = 'Aktív feladatok';
if (staff) { if (staff) {
...@@ -245,19 +321,21 @@ class Homework extends Component { ...@@ -245,19 +321,21 @@ class Homework extends Component {
} }
if ( if (
this.props.homeworks.tasks.filter(task => this.props.homeworks.tasks.filter(
moment().isBefore(task.deadline) === active).length === 0 (task) => moment().isBefore(task.deadline) === active
).length === 0
) { ) {
empty = true; noTask = true;
} }
if (!active) { if (!active) {
if (staff) { if (staff) {
headerText = 'Lejárt határidejű feladatok kijavítása, módosítása vagy törlése'; headerText =
'Lejárt határidejű feladatok kijavítása, módosítása vagy törlése';
} else { } else {
headerText = 'Lejárt határidejű feladatok'; headerText = 'Lejárt határidejű feladatok';
} }
emptyText = 'Jelenleg nincs egyetlen lejárt határidejű feladat sem.'; noTaskText = 'Jelenleg nincs egyetlen lejárt határidejű feladat sem.';
marginBottom = '3em'; marginBottom = '3em';
} }
...@@ -265,47 +343,71 @@ class Homework extends Component { ...@@ -265,47 +343,71 @@ class Homework extends Component {
<Segment style={{ padding: '0 0 2em 0' }} vertical basic> <Segment style={{ padding: '0 0 2em 0' }} vertical basic>
<Container> <Container>
<Header <Header
as='h1' as="h1"
dividing dividing
content={headerText} content={headerText}
style={{ style={{
fontSize: '2em', fontSize: '2em',
fontWeight: 'normal',
marginBottom: 0,
marginTop: '0.5em',
}}
/>
{noTask ? (
customMessage(noTaskHeaderText, noTaskText, marginBottom, false)
) : (
<div>{this.renderHomeworksTable(active, staff)}</div>
)}
{!active && !staff ? (
<Header
as="h3"
content={
<div>
Jelenlegi bitjeid száma:
<Label color="green" size="large">
{this.props.user.bits} bit
</Label>
</div>
}
style={{
fontWeight: 'normal', fontWeight: 'normal',
marginBottom: 0,
marginTop: '0.5em', marginTop: '0.5em',
marginBottom: '1em',
}} }}
/> textAlign="right"
{empty />
? emptyMessage(emptyHeaderText, emptyText, marginBottom, false) ) : null}
: this.renderHomeworksTable(active, staff)}
</Container> </Container>
</Segment> </Segment>
); );
} }
render() { render() {
if (this.props.user.role === 'Student') { const { user } = this.props;
if (user.role === 'Student') {
return ( return (
<div> <div style={{ paddingBottom: '2em' }}>
{this.renderHomeworks(true, false)} {this.renderHomeworks(true, false)}
{this.renderHomeworks(false, false)} {this.renderHomeworks(false, false)}
</div> </div>
); );
} else if (this.props.user.role === 'Staff') { }
if (user.role === 'Staff') {
return ( return (
<div> <div style={{ paddingBottom: '2em' }}>
<Segment style={{ padding: '0 0 2em 0' }} vertical basic> <Segment style={{ padding: '0 0 2em 0' }} vertical basic>
<Container> <Container>
<Header <Header
as='h1'
dividing dividing
content='Új házi feladat létrehozása' as="h1"
content="Új házi feladat létrehozása"
style={{ style={{
fontSize: '2em', fontSize: '2em',
fontWeight: 'normal', fontWeight: 'normal',
marginBottom: '0.5em', marginBottom: '0.5em',
marginTop: '0.5em', marginTop: '0.5em',
}} }}
/> />
<Button.Group> <Button.Group>
<AddTaskForm /> <AddTaskForm />
...@@ -317,22 +419,22 @@ class Homework extends Component { ...@@ -317,22 +419,22 @@ class Homework extends Component {
</div> </div>
); );
} }
return null; return null; // ¯\_(ツ)_/¯
} }
} }
const mapStateToProps = ({ selectedTask, homeworks, user }) => ({ selectedTask, homeworks, user }); const mapStateToProps = ({ selectedTask, homeworks, user }) => ({
selectedTask,
homeworks,
user,
});
export default connect( export default connect(mapStateToProps, {
mapStateToProps, getTasks,
{ setSelectedTask,
getTasks, getSolutions,
setSelectedTask, getDocuments,
getSolutions, addTask,
addTask, deleteTask,
deleteTask, getProfiles,
addDocument, })(Homework);
getProfiles,
getDocuments,
},
)(Homework);
import { Container, Table } from 'semantic-ui-react';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { getTrainees } from '../../actions/statistics';
class LeaderBoard extends Component {
UNSAFE_componentWillMount() {
this.props.getTrainees();
}
// Every event rendered
renderTraineeBits() {
return this.props.trainees
.sort(
(a, b) =>
(Number(b.homework_bits) + Number(b.events_visited) + Number(b.extra_bits)) -
(Number(a.homework_bits) + Number(a.events_visited) + Number(a.extra_bits))
)
.map((trainee) =>
trainee.role === 'Student' ? (
<Table.Row key={trainee.nick}>
<Table.Cell textAlign="center">{trainee.full_name}</Table.Cell>
<Table.Cell textAlign="center">{trainee.events_visited}</Table.Cell>
<Table.Cell textAlign="center">
{Number(trainee.homework_bits) + Number(trainee.extra_bits)}
</Table.Cell>
<Table.Cell textAlign="center">
{Number(trainee.homework_bits) + trainee.events_visited + Number(trainee.extra_bits)}
</Table.Cell>
</Table.Row>
) : null
);
}
render() {
return (
<Container textAlign="center" style={{ overflowX: 'scroll' }}>
<Table color="blue" unstackable celled selectable compact>
<Table.Header>
<Table.Row>
<Table.HeaderCell textAlign="center">Képződők</Table.HeaderCell>
<Table.HeaderCell textAlign="center">Jelenlét</Table.HeaderCell>
<Table.HeaderCell textAlign="center">Bitek</Table.HeaderCell>
<Table.HeaderCell textAlign="center">Szumma</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{this.props.trainees ? (
this.renderTraineeBits()
) : (
<Table.Row>
<Table.Cell>Nincsenek képződők</Table.Cell>
</Table.Row>
)}
</Table.Body>
</Table>
</Container>
);
}
}
const mapStateToProps = ({ trainees: { trainees }, user }) => ({
trainees,
user,
});
export default connect(mapStateToProps, { getTrainees })(LeaderBoard);
import {
Card,
Container,
Header,
Icon,
Image,
Item,
Label,
Responsive,
Segment,
} from 'semantic-ui-react';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { getMentors } from '../../actions/mentors';
class Mentors extends Component {
UNSAFE_componentWillMount() {
this.props.getMentors();
}
renderMentorsNormal() {
return this.props.mentors.map((item, index) => (
<Card style={{ maxWidth: '100%', minWidth: '100%' }}>
<Card.Content style={{ padding: '0' }}>
<Item.Group>
<Item>
{index % 2 === 0 ? (
<Item.Image size="medium" src={item.image} />
) : null}
<Item.Content style={{ padding: '1rem' }}>
<Item.Header>{item.name}</Item.Header>
<Item.Description>
<p dangerouslySetInnerHTML={{ __html: item.text }}></p>
</Item.Description>
<Item.Extra>
<Label>
<Icon name="mail" />
{item.email}
</Label>
</Item.Extra>
</Item.Content>
{index % 2 === 1 ? (
<Item.Image size="medium" src={item.image} />
) : null}
</Item>
</Item.Group>
</Card.Content>
</Card>
));
}
renderMentorsMobile() {
return this.props.mentors.map((item) => (
<Card key={item.id}>
<Image src={item.image} wrapped ui={false} />
<Card.Content>
<Card.Header>{item.name}</Card.Header>
<Card.Description>
<p dangerouslySetInnerHTML={{ __html: item.text }}></p>
</Card.Description>
</Card.Content>
<Card.Content extra>
<Label>
<Icon name="mail" />
{item.email}
</Label>
</Card.Content>
</Card>
));
}
render() {
return (
<div>
<Segment inverted textAlign="center" vertical>
<Container>
<Header
as="h1"
content="Mentorok"
inverted
style={{
fontSize: '3em',
fontWeight: 'normal',
marginBottom: 0,
marginTop: '0.5em',
}}
/>
</Container>
</Segment>
<Responsive minWidth={768}>
<Container style={{ paddingTop: '2em', paddingBottom: '5em' }}>
{this.renderMentorsNormal()}
</Container>
</Responsive>
<Responsive minWidth={551} maxWidth={767}>
<Container style={{ paddingTop: '2em', paddingBottom: '5em' }}>
<Card.Group centered itemsPerRow={2}>
{this.renderMentorsMobile()}
</Card.Group>
</Container>
</Responsive>
<Responsive maxWidth={550}>
<Container style={{ paddingTop: '2em', paddingBottom: '5em' }}>
<Card.Group centered itemsPerRow={1}>
{this.renderMentorsMobile()}
</Card.Group>
</Container>
</Responsive>
</div>
);
}
}
const mapStateToProps = ({ mentors, user }) => ({ mentors, user });
export default connect(mapStateToProps, { getMentors })(Mentors);
.news-extra { .news-extra {
color: grey; color: grey;
font-size: 0.75em; font-size: 0.75em;
font-style: italic; font-style: italic;
font-family: fantasy; font-family: fantasy;
text-align: justify; text-align: justify;
} }
.news-text { .news-text {
font-size: 1.15em; font-size: 1.15em;
font-family: Arial, Helvetica, sans-serif; font-family: Arial, Helvetica, sans-serif;
text-align: justify; text-align: justify;
} }