diff --git a/assets/js/VacancyPage.jsx b/assets/js/VacancyPage.jsx index 2f18490f55e2a3132eb35b59fc1809785925ea5e..96fee2dc32709926b567b2147494356aea83caad 100755 --- a/assets/js/VacancyPage.jsx +++ b/assets/js/VacancyPage.jsx @@ -1,8 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { - Segment, Button, Dropdown, Container, -} from 'semantic-ui-react'; +import { Segment, Button, Dropdown, Container } from 'semantic-ui-react'; import { Link } from 'react-router'; import Tabs from './components/Tabs'; import Pane from './components/Pane'; @@ -16,17 +14,17 @@ export default class VacancyPage extends React.Component { }; static getId(user) { - const { role } = user; + const role = user.role; if (role === 'student') { return user.data.student.id; - } if ( - role === 'company' - || (role === 'admin' && user.data.company != null) + } else if ( + role === 'company' || + (role === 'admin' && user.data.company != null) ) { return user.data.company.id; - } if ( - role === 'supervisor' - || (role === 'admin' && user.data.supervisor != null) + } else if ( + role === 'supervisor' || + (role === 'admin' && user.data.supervisor != null) ) { return user.data.supervisor.id; } @@ -60,81 +58,81 @@ export default class VacancyPage extends React.Component { <Pagination key={1} url="/vacancies/" - child={( + child={ <VacancyList user={this.props.user} key={1} userId={this.state.id} sort={this.state.sort} /> - )} + } /> </Pane> <Pane label="Lamaran Saya"> <Pagination key={2} url={`/students/${this.state.id}/applied-vacancies/`} - child={( + child={ <VacancyList user={this.props.user} key={2} userId={this.state.id} /> - )} + } /> </Pane> <Pane label="Ditandai"> <Pagination key={3} url={`/students/${this.state.id}/bookmarked-vacancies/`} - child={( + child={ <VacancyList key={3} user={this.props.user} userId={this.state.id} /> - )} + } /> </Pane> <Pane label="Lowongan Tersedia"> <Pagination key={4} url="/vacancies/opened_only=1" - child={( + child={ <VacancyList user={this.props.user} key={4} userId={this.state.id} /> - )} + } /> </Pane> </Tabs> ); - } if ( - (this.props.user.role === 'admin' - && this.props.user.data.company != null) - || this.props.user.role === 'company' + } else if ( + (this.props.user.role === 'admin' && + this.props.user.data.company != null) || + this.props.user.role === 'company' ) { return ( <Segment className="paginationCompany"> <Pagination key={1} url={`/companies/${this.state.id}/vacancies/`} - child={( + child={ <VacancyList key={1} user={this.props.user} userId={this.state.id} /> - )} + } error="Akun anda belum terverifikasi. Harap hubungi pihak administrasi" /> </Segment> ); - } if ( - this.props.user.role === 'admin' - || this.props.user.role === 'supervisor' + } else if ( + this.props.user.role === 'admin' || + this.props.user.role === 'supervisor' ) { return ( <Tabs selected={0}> @@ -142,26 +140,26 @@ export default class VacancyPage extends React.Component { <Pagination key={1} url="/vacancies/?verified=false" - child={( + child={ <VacancyList user={this.props.user} key={1} userId={this.state.id} /> - )} + } /> </Pane> <Pane label="Lowongan Terverifikasi"> <Pagination key={2} url="/vacancies/?verified=true" - child={( + child={ <VacancyList user={this.props.user} key={2} userId={this.state.id} /> - )} + } /> </Pane> </Tabs> @@ -180,9 +178,9 @@ export default class VacancyPage extends React.Component { companyHeader() { if ( - (this.props.user.role === 'admin' - && this.props.user.data.company != null) - || this.props.user.role === 'company' + (this.props.user.role === 'admin' && + this.props.user.data.company != null) || + this.props.user.role === 'company' ) { return ( <div style={{ float: 'left' }}> @@ -233,8 +231,8 @@ export default class VacancyPage extends React.Component { style={{ display: 'inline-block' }} > {this.companyHeader()} - {(this.props.user.role === 'admin' - || this.props.user.role === 'supervisor') && ( + {(this.props.user.role === 'admin' || + this.props.user.role === 'supervisor') && ( <Button as={Link} to="/rekap" diff --git a/assets/js/components/TopMenu.jsx b/assets/js/components/TopMenu.jsx index 07fb0e44ae3a4d6ae78071968fc22634dcc1e35f..42c319868a96d17041f963e14a7cc9d3ea4da87c 100755 --- a/assets/js/components/TopMenu.jsx +++ b/assets/js/components/TopMenu.jsx @@ -1,16 +1,13 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { - Menu, Image, Popup, Card, Button, -} from 'semantic-ui-react'; +import { Menu, Image, Popup, Card, Button } from 'semantic-ui-react'; import { Link, browserHistory } from 'react-router'; -import moment from 'moment'; import Server from '../lib/Server'; import Storage from '../lib/Storage'; +import moment from 'moment'; import ModalAlert from './ModalAlert'; -const quotes = require('starwars'); - +var quotes = require('starwars'); const defaultPicture = 'https://semantic-ui.com/images/avatar/small/elliot.jpg'; export default class TopMenu extends React.Component { @@ -22,12 +19,12 @@ export default class TopMenu extends React.Component { }, photo: null, }; - const { role } = user; + const role = user.role; if (role === 'student') { return user.data.student; - } if (role === 'company') { + } else if (role === 'company') { return user.data.company; - } if (role === 'supervisor') { + } else if (role === 'supervisor') { return user.data.supervisor; } @@ -47,19 +44,19 @@ export default class TopMenu extends React.Component { activeItem: this.menuActiveState(), logoutLoading: false, currentDate: - `${moment(new Date()).format('dddd') - }, ${ - moment(new Date()).format('LL')}`, + moment(new Date()).format('dddd') + + ', ' + + moment(new Date()).format('LL'), todayQuote: quotes(), isOpen: false, applianceInformation: - '1. Pastikan anda sudah mengupdate profile anda\n' - + '2. Cari lowongan internship yang ada di tab lowongan\n' - + "3. Klik tombol 'Detail'\n" - + '4. Pastikan persyaratan sudah terpenuhi\n' - + "5. Jelaskan mengapa anda ingin mengikuti lowongan internship tersebut di 'Cover Letter'\n" - + "6. Klik tombol 'Daftar'\n", - kapeDescription: 'Kanal Akses Pendaftaran KP Elektronik', + "1. Pastikan anda sudah mengupdate profile anda\n" + + "2. Cari lowongan internship yang ada di tab lowongan\n" + + "3. Klik tombol 'Detail'\n" + + "4. Pastikan persyaratan sudah terpenuhi\n" + + "5. Jelaskan mengapa anda ingin mengikuti lowongan internship tersebut di 'Cover Letter'\n"+ + "6. Klik tombol 'Daftar'\n", + kapeDescription: "Kanal Akses Pendaftaran KP Elektronik" }; @@ -71,7 +68,7 @@ export default class TopMenu extends React.Component { } handleItemClick = (e, { name }) => { - if (name === 'Logo') { + if(name === 'Logo') { this.setState({ activeItem: 'Beranda' }); } else { this.setState({ activeItem: name }); @@ -79,16 +76,18 @@ export default class TopMenu extends React.Component { } handleOpen = () => { + this.setState({ - isOpen: true, + isOpen: true }); - }; + + }; handleClose = () => { this.setState({ - isOpen: false, + isOpen: false }); - clearTimeout(this.timeout); + clearTimeout(this.timeout) }; @@ -150,16 +149,9 @@ export default class TopMenu extends React.Component { <div className="admin-bar"> <p> Anda login sebagai perusahaan: - <b> - {' '} - {this.props.user.data.company.name} - </b> - {' '} -(# - {this.props.user.data.company.id} -). Untuk kembali menjadi admin, - klik - {' '} + <b> {this.props.user.data.company.name}</b> (# + {this.props.user.data.company.id}). Untuk kembali menjadi admin, + klik{' '} <a href="#" onClick={this.logoutCompany}> {' '} link ini @@ -174,44 +166,43 @@ export default class TopMenu extends React.Component { /> <Menu color="blue" pointing secondary> <Menu.Menu position="left"> - <Menu.Item style={{ padding: '0px' }} as={Link} to="/home" name="Logo" onClick={this.handleItemClick}> - <Image size="small" src="/assets/img/logo.png" /> - {this.state.kapeDescription} - </Menu.Item> + <Menu.Item style={{ padding: '0px' }} as={Link} to="/home" name="Logo" onClick={this.handleItemClick}> + <Image size="small" src="/assets/img/logo.png" /> + {this.state.kapeDescription} + </Menu.Item> </Menu.Menu> <Menu.Menu position="right"> - {this.props.user.role === 'student' && ( + {this.props.user.role === 'student' && ( <Menu.Item>{btn}</Menu.Item> - )} + )} <Menu.Item style={{ margin: '3px' }}> {this.state.currentDate} </Menu.Item> <Menu.Item as={Link} to="/home" name="Beranda" active={activeItem === 'Beranda'} onClick={this.handleItemClick} /> - { this.props.user.role === 'company' - && <Menu.Item as={Link} to="/profil-perusahaan" name="Profil" active={activeItem === 'Profil'} onClick={this.handleItemClick} /> } - { this.props.user.data.is_staff - && <Menu.Item as={Link} to="/lowongan" name="Lowongan" active={activeItem === 'Lowongan'} onClick={this.handleItemClick} /> } + { this.props.user.role === 'company' && + <Menu.Item as={Link} to="/profil-perusahaan" name="Profil" active={activeItem === 'Profil'} onClick={this.handleItemClick} /> } + { this.props.user.data.is_staff && + <Menu.Item as={Link} to="/lowongan" name="Lowongan" active={activeItem === 'Lowongan'} onClick={this.handleItemClick} /> } <Menu.Item as={Link} to="/notifikasi" name="Notifikasi" active={activeItem === 'Notifikasi'} onClick={this.handleItemClick} /> <Menu.Item style={{ padding: '10px 0' }}> <Popup trigger={<Image src={(this.props.user.role === 'company' ? data.logo : data.photo) || defaultPicture} avatar />} open={this.state.isOpen} - on="click" - onClose={this.handleClose} - onOpen={this.handleOpen} + on='click' + onClose={this.handleClose} + onOpen={this.handleOpen} > <Card header={data.name} description={data.user.email} /> - { this.props.user.role === 'student' - && <Menu.Item as={Link} to="/profil-mahasiswa" style={{ margin: '10px' }} name="Profil" active={activeItem === 'Profil'} onClick={this.handleItemClick} /> } - <Menu.Item as={Link} to="/edit-profil-mahasiswa" style={{ margin: '10px' }} name="Edit Profil" active={activeItem === 'EditProfil'} onClick={this.handleItemClick} /> - <Button.Group floated="right"> - <Button as={Link} onClick={this.logout} loading={this.state.logoutLoading} name="logout" color="blue" size="tiny">Keluar</Button> - </Button.Group> + { this.props.user.role === 'student' && + <Menu.Item as={Link} to="/profil-mahasiswa" style={{ margin: '10px' }} name="Profil" active={activeItem === 'Profil'} onClick={this.handleItemClick} /> } + <Menu.Item as={Link} to="/edit-profil-mahasiswa" style={{ margin: '10px' }} name="Edit Profil" active={activeItem === 'EditProfil'} onClick={this.handleItemClick} /> + <Button.Group floated="right"> + <Button as={Link} onClick={this.logout} loading={this.state.logoutLoading} name="logout" color="blue" size="tiny">Keluar</Button></Button.Group> </Popup> </Menu.Item> </Menu.Menu> diff --git a/assets/js/components/Vacancy.jsx b/assets/js/components/Vacancy.jsx index f56b081cd7edeb339c734292ada72250c20eeb11..069b419c59f162b6a6e849456bdab776b1e8378a 100755 --- a/assets/js/components/Vacancy.jsx +++ b/assets/js/components/Vacancy.jsx @@ -1,8 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { - Item, Rating, Button, Grid, -} from 'semantic-ui-react'; +import { Item, Rating, Button, Grid } from 'semantic-ui-react'; import moment from 'moment'; import ApplyModal from './ApplyModal'; import Server from '../lib/Server'; @@ -47,7 +45,7 @@ export default class Vacancy extends React.Component { this.state = { bookmarked: this.props.bookmarked, registeredStatus: this.props.status, - reason: ' ', + reason: " ", deleteLoading: false, }; moment.locale('id'); @@ -83,7 +81,8 @@ export default class Vacancy extends React.Component { this.state.bookmarked = 1 - this.state.bookmarked; } - updateStatus = (registeredStatus = null) => this.setState({ registeredStatus }); + updateStatus = (registeredStatus = null) => + this.setState({ registeredStatus }); removeVacancyApplication() { this.setState({ deleteLoading: true }); @@ -160,11 +159,11 @@ export default class Vacancy extends React.Component { if (this.state.registeredStatus == null) { return applyModal; - } if ( + } else if ( this.state.registeredStatus === Vacancy.APPLICATION_STATUS.REJECTED ) { return rejectedButton; - } if ( + } else if ( this.state.registeredStatus === Vacancy.APPLICATION_STATUS.ACCEPTED ) { return acceptedButton; @@ -175,55 +174,40 @@ export default class Vacancy extends React.Component { generateContent() { if (this.state.registeredStatus == Vacancy.APPLICATION_STATUS.REJECTED) { Server.get(`/students/${this.props.user.data.student.id}/applied-vacancies/${this.props.data.id}/reason/`, - false).then( + false).then( (data) => { - this.setState({ reason: data.reason }); + this.setState({reason: data.reason}); }, ); return ( - <p> - <br /> - <b>Alasan ditolak:</b> - {' '} - {this.state.reason} - {' '} - </p> + <p><br/><b>Alasan ditolak:</b> {this.state.reason} </p> ); - } - return ( + + } else { + return ( <p> - {this.props.data.company.address} - <br /> - {this.props.data.working_period} - <br /> - {this.state.count} - {' '} -orang telah mendaftar! - <br /> - <b> - {this.props.data.total_accepted_applicants} -/ - {' '} - {this.props.data.max_accepted_applicants} - diterima - {' '} - </b> - <br /> - <b> - {`Ditutup ${moment( - moment(this.props.data.close_time), - ).fromNow()}`} - </b> - <br /> - Rp. - {' '} - {this.props.data.salary} - {' '} - <br /> - <b>{this.props.data.apply_before}</b> + {this.props.data.company.address} + <br /> + {this.props.data.working_period} + <br /> + {this.state.count} orang telah mendaftar! + <br /> + <b> + {this.props.data.total_accepted_applicants}/{' '} + {this.props.data.max_accepted_applicants} + diterima{' '} + </b> + <br /> + <b>{`Ditutup ${moment( + moment(this.props.data.close_time), + ).fromNow()}`}</b> + <br /> + Rp. {this.props.data.salary} <br /> + <b>{this.props.data.apply_before}</b> </p> - ); + ); + } } render() { @@ -270,8 +254,7 @@ orang telah mendaftar! /> </Grid.Row> <Grid.Row> - {this.generateAction()} - </Grid.Row> + {this.generateAction()}</Grid.Row> </Grid.Column> </Grid.Row> </Item.Extra> diff --git a/assets/js/components/VacancyList.jsx b/assets/js/components/VacancyList.jsx index c00965d123907a685a6726712e84b4ae61352f8e..819b8191eb28de424922da6bb4b42006d834f5cd 100755 --- a/assets/js/components/VacancyList.jsx +++ b/assets/js/components/VacancyList.jsx @@ -1,13 +1,11 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { - Item, Grid, Container, Dropdown, -} from 'semantic-ui-react'; -import moment from 'moment'; +import { Item, Grid, Container, Dropdown } from 'semantic-ui-react'; import Vacancy from './Vacancy'; import CompanyVacancy from './CompanyVacancy'; import AdminVacancy from './AdminVacancy'; import Server from '../lib/Server'; +import moment from 'moment'; export default class VacancyList extends React.Component { static propTypes = { @@ -61,22 +59,24 @@ export default class VacancyList extends React.Component { this.setState({ vacancies: obj }); } - deleteVacancy = (id) => Server.delete(`/vacancies/${id}/`, this.state).then( - () => { - this.modalAlert.open('Hapus Lowongan', 'Lowongan berhasil dihapus'); - const newVacancies = []; - this.state.vacancies.map( - (vacancy) => vacancy.id !== id && newVacancies.push(vacancy), - ); - this.setState({ vacancies: newVacancies }); - }, - (error) => error.then((r) => { - this.modalAlert.open('Gagal Menghapus Lowongan', r.error); - }), - ); + deleteVacancy = (id) => + Server.delete(`/vacancies/${id}/`, this.state).then( + () => { + this.modalAlert.open('Hapus Lowongan', 'Lowongan berhasil dihapus'); + const newVacancies = []; + this.state.vacancies.map( + (vacancy) => vacancy.id !== id && newVacancies.push(vacancy), + ); + this.setState({ vacancies: newVacancies }); + }, + (error) => + error.then((r) => { + this.modalAlert.open('Gagal Menghapus Lowongan', r.error); + }), + ); filterVacanciesBasedOnSalary = (vacancies) => { - const { salaryFilter } = this.state; + const salaryFilter = this.state.salaryFilter; let filteredVacancies = vacancies; if (salaryFilter === 1) { filteredVacancies = filteredVacancies.filter( @@ -84,13 +84,15 @@ export default class VacancyList extends React.Component { ); } else if (salaryFilter === 2) { filteredVacancies = filteredVacancies.filter( - (vacancy) => vacancy.props.data.salary >= 1000000 - && vacancy.props.data.salary < 3000000, + (vacancy) => + vacancy.props.data.salary >= 1000000 && + vacancy.props.data.salary < 3000000, ); } else if (salaryFilter === 3) { filteredVacancies = filteredVacancies.filter( - (vacancy) => vacancy.props.data.salary >= 3000000 - && vacancy.props.data.salary < 5000000, + (vacancy) => + vacancy.props.data.salary >= 3000000 && + vacancy.props.data.salary < 5000000, ); } else if (salaryFilter === 4) { filteredVacancies = filteredVacancies.filter( @@ -102,7 +104,7 @@ export default class VacancyList extends React.Component { }; filterVacanciesBasedOnVacancyStatus = (vacancies) => { - const { vacancyStateFilter } = this.state; + const vacancyStateFilter = this.state.vacancyStateFilter; let filteredVacancies = vacancies; if (vacancyStateFilter === 1) { filteredVacancies = filteredVacancies.filter( @@ -151,17 +153,21 @@ export default class VacancyList extends React.Component { /> )); if (this.props.sort === 'ASC') { - return vacancies.sort((vac1, vac2) => vac1.props.data.name.localeCompare(vac2.props.data.name)); - } if (this.props.sort === 'DESC') { - return vacancies.sort((vac1, vac2) => vac2.props.data.name.localeCompare(vac1.props.data.name)); + return vacancies.sort((vac1, vac2) => { + return vac1.props.data.name.localeCompare(vac2.props.data.name); + }); + } else if (this.props.sort === 'DESC') { + return vacancies.sort((vac1, vac2) => { + return vac2.props.data.name.localeCompare(vac1.props.data.name); + }); } vacancies = this.filterVacanciesBasedOnSalary(vacancies); vacancies = this.filterVacanciesBasedOnVacancyStatus(vacancies); return vacancies; - } if ( - (this.props.user.role === 'admin' - && this.props.user.data.company != null) - || this.props.user.role === 'company' + } else if ( + (this.props.user.role === 'admin' && + this.props.user.data.company != null) || + this.props.user.role === 'company' ) { return this.state.vacancies.map((vacancy) => ( <Item.Group key={vacancy.id} relaxed style={{ width: '100%' }}> diff --git a/core/views/accounts/student.py b/core/views/accounts/student.py index 029b03acaef7351d69c046665a4ac3837b56a5c5..de2b7ebf4b351f8ecd1d5764b7fbe014a9dc5776 100644 --- a/core/views/accounts/student.py +++ b/core/views/accounts/student.py @@ -50,36 +50,32 @@ class StudentViewSet(viewsets.ModelViewSet): elif 'pdf_file' in request.data.keys(): return self.__profile_helper('pdf_file', request, user) - if 'github_url' in request.data.keys(): - if not re.search(github_url_pattern, request.data['github_url']): - return Response( - {'Error': "Pastikan link github yang anda tulis benar. (Berpola : https://github.com/<username>"}, - status=status.HTTP_400_BAD_REQUEST) - - if 'linkedin_url' in request.data.keys(): - if not re.search(linkedin_url_pattern, request.data['linkedin_url']): - return Response({ - 'Error': "Pastikan link linkedin yang anda tulis benar. (Berpola : " - "https://linkedin.com/in/<username>"}, - status=status.HTTP_400_BAD_REQUEST) - - if 'hackerrank_url' in request.data.keys(): - if not re.search(hackerrank_url_pattern, - request.data['hackerrank_url']): - return Response({ - 'Error': "Pastikan link hackerrank yang anda tulis benar. (Berpola : " - "https://hackerrank.com/<username>"}, - status=status.HTTP_400_BAD_REQUEST) + if 'github_url' in request.data.keys() and not re.search(github_url_pattern, request.data['github_url']): + return Response( + {'Error': "Pastikan link github yang anda tulis benar. (Berpola : https://github.com/<username>"}, + status=status.HTTP_400_BAD_REQUEST) + + if 'linkedin_url' in request.data.keys() and not re.search(linkedin_url_pattern, request.data['linkedin_url']): + return Response({ + 'Error': "Pastikan link linkedin yang anda tulis benar. (Berpola : " + "https://linkedin.com/in/<username>"}, + status=status.HTTP_400_BAD_REQUEST) + + if 'hackerrank_url' in request.data.keys() and not re.search(hackerrank_url_pattern, + request.data['hackerrank_url']): + return Response({ + 'Error': "Pastikan link hackerrank yang anda tulis benar. (Berpola : " + "https://hackerrank.com/<username>"}, + status=status.HTTP_400_BAD_REQUEST) return self.profile_serialize(request, user) def profile_serialize(self, request, user): serializer = self.serializer_class(user, data=request.data, partial=True) if serializer.is_valid(): - if serializer.validated_data.get('skills') is not None: - if serializer.validated_data.get( - 'skills').isdigit(): - return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + if serializer.validated_data.get('skills') is not None and serializer.validated_data.get( + 'skills').isdigit(): + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) serializer.save() return Response(serializer.data, status=status.HTTP_202_ACCEPTED) else: