Fakultas Ilmu Komputer UI

Commit 4b65b513 authored by Reza Qorib's avatar Reza Qorib
Browse files

Merge branch 'Features/VerifyVacancyForAdmin' into 'develop'

Verify vacancy for admin and supervisor

See merge request !20
parents 1ce99a41 34b38d89
...@@ -244,7 +244,6 @@ card .formRegis{ ...@@ -244,7 +244,6 @@ card .formRegis{
margin-right: 10%; margin-right: 10%;
} }
.admin-bar{ .admin-bar{
margin: 0; margin: 0;
padding: 0 10px 0 0; padding: 0 10px 0 0;
...@@ -252,4 +251,5 @@ card .formRegis{ ...@@ -252,4 +251,5 @@ card .formRegis{
text-align: right; text-align: right;
background-color: #304D8A; background-color: #304D8A;
color: white; color: white;
} }
\ No newline at end of file
...@@ -12,6 +12,7 @@ export default class CompanyPage extends React.Component { ...@@ -12,6 +12,7 @@ export default class CompanyPage extends React.Component {
}; };
handleClick = () => window.open('/admin/'); handleClick = () => window.open('/admin/');
handleVacancy = () => window.open('/lowongan');
render() { render() {
return ( return (
...@@ -19,6 +20,11 @@ export default class CompanyPage extends React.Component { ...@@ -19,6 +20,11 @@ export default class CompanyPage extends React.Component {
<div style={{ paddingLeft: '10px' }}> <div style={{ paddingLeft: '10px' }}>
<Button onClick={this.handleClick} icon="dashboard" labelPosition="left" color="facebook" content="Buka Menu Administrasi" /> <Button onClick={this.handleClick} icon="dashboard" labelPosition="left" color="facebook" content="Buka Menu Administrasi" />
</div> </div>
<div style={{ paddingLeft: '10px', paddingTop : '10px'}}>
<Button onClick={this.handleVacancy} icon="dashboard" labelPosition="left" color="facebook" content="Halaman Verifikasi Lowongan" />
</div>
<Tabs selected={0}> <Tabs selected={0}>
<Pagination <Pagination
key={1} key={1}
......
import React from 'react'; import React from 'react';
import TopMenu from './components/TopMenu'; import TopMenu from './components/TopMenu';
import Server from './lib/Server';
import Footer from './components/Footer'; import Footer from './components/Footer';
export default class Dashboard extends React.Component { export default class Dashboard extends React.Component {
static propTypes = { static propTypes = {
user: React.PropTypes.object.isRequired,
route: React.PropTypes.object.isRequired,
params: React.PropTypes.object.isRequired,
children: React.PropTypes.oneOfType([ children: React.PropTypes.oneOfType([
React.PropTypes.arrayOf(React.PropTypes.node), React.PropTypes.arrayOf(React.PropTypes.node),
React.PropTypes.node, React.PropTypes.node,
...@@ -11,6 +15,11 @@ export default class Dashboard extends React.Component { ...@@ -11,6 +15,11 @@ export default class Dashboard extends React.Component {
user: React.PropTypes.object.isRequired, user: React.PropTypes.object.isRequired,
}; };
constructor(props) {
super(props);
/* istanbul ignore next */
}
render = () => ( render = () => (
<div> <div>
<TopMenu user={this.props.user} /> <TopMenu user={this.props.user} />
......
import React from 'react'; import React from 'react';
import { Container } from 'semantic-ui-react'; import { Container, Item } from 'semantic-ui-react';
import Tabs from './components/Tabs'; import Tabs from './components/Tabs';
import Pane from './components/Pane'; import Pane from './components/Pane';
import VacancyList from './components/VacancyList'; import VacancyList from './components/VacancyList';
import AdminVacancy from './components/AdminVacancy';
import Pagination from './components/Pagination'; import Pagination from './components/Pagination';
export default class VacancyPage extends React.Component { export default class VacancyPage extends React.Component {
...@@ -15,8 +16,10 @@ export default class VacancyPage extends React.Component { ...@@ -15,8 +16,10 @@ export default class VacancyPage extends React.Component {
const role = user.role; const role = user.role;
if (role === 'student') { if (role === 'student') {
return user.data.student.id; return user.data.student.id;
} else if (role === 'company' || role === 'admin') { } else if (role === 'company' || (role === 'admin' && user.data.company != null)) {
return user.data.company.id; return user.data.company.id;
} else if (role === 'supervisor' || role === 'admin' && user.data.supervisor != null){
return user.data.supervisor.id;
} }
return 0; return 0;
...@@ -31,6 +34,7 @@ export default class VacancyPage extends React.Component { ...@@ -31,6 +34,7 @@ export default class VacancyPage extends React.Component {
}; };
} }
generateVacancies() { generateVacancies() {
if (this.props.user.role === 'student') { if (this.props.user.role === 'student') {
return ( return (
...@@ -76,7 +80,7 @@ export default class VacancyPage extends React.Component { ...@@ -76,7 +80,7 @@ export default class VacancyPage extends React.Component {
</Pane> </Pane>
</Tabs> </Tabs>
); );
} else if (this.props.user.role === 'company' || this.props.user.role === 'admin') { } else if (this.props.user.role === 'company') {
return ( return (
<Container className="vacancies"> <Container className="vacancies">
<Pagination <Pagination
...@@ -93,6 +97,37 @@ export default class VacancyPage extends React.Component { ...@@ -93,6 +97,37 @@ export default class VacancyPage extends React.Component {
/> />
</Container> </Container>
); );
} else if (this.props.user.role === 'admin' || this.props.user.role === 'supervisor') {
return (
<Tabs selected={0}>
<Pane label="Lowongan Belum Terverifikasi" >
<Pagination
key={1}
url="/vacancies/?verified=false"
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={
<VacancyList
user={this.props.user}
key={2}
userId={this.state.id}
/>
}
/>
</Pane>
</Tabs>
);
} }
return ( return (
......
...@@ -43,7 +43,7 @@ describe('CompanyPage', () => { ...@@ -43,7 +43,7 @@ describe('CompanyPage', () => {
it('click dashboard button problem', () => { it('click dashboard button problem', () => {
const companyPage = ReactTestUtils.renderIntoDocument( const companyPage = ReactTestUtils.renderIntoDocument(
<CompanyPage user={adminUser} />); <CompanyPage user={adminUser} />);
const dashboardButton = ReactTestUtils.findRenderedDOMComponentWithTag(companyPage, 'Button'); const dashboardButton = ReactTestUtils.scryRenderedDOMComponentsWithTag(companyPage, 'Button')[0];
ReactTestUtils.Simulate.click(dashboardButton); ReactTestUtils.Simulate.click(dashboardButton);
expect(companyPage).to.exist; expect(companyPage).to.exist;
expect(dashboardButton).to.exist; expect(dashboardButton).to.exist;
......
/* eslint-disable no-unused-expressions */
import React from 'react';
import ReactTestUtils from 'react-addons-test-utils';
import AdminVacancy from '../../components/AdminVacancy';
import Storage from '../../lib/Storage';
describe('Vacancy', () => {
const fetchMock = require('fetch-mock');
const response = {
close_time: '2019-03-28T05:55:42Z',
company: {
address: 'kebayoran baru',
id: 1,
logo: null,
name: 'tutup lapak',
},
created: '2017-03-28T07:05:47.128672Z',
description: 'Lorem ipsum dolbh.',
id: 3,
name: 'Software Engineer',
open_time: '2017-03-28T05:55:38Z',
updated: '2017-03-28T07:34:13.122093Z',
verified: true,
};
const response2 = {
close_time: '2019-03-28T05:55:42Z',
company: {
address: 'kebayoran baru',
id: 1,
logo: 'pictures',
name: 'tutup lapak',
},
created: '2017-03-28T07:05:47.128672Z',
description: 'Lorem ipsum dolbh.',
id: 3,
name: 'Software Engineer',
open_time: '2017-03-28T05:55:38Z',
updated: '2017-03-28T07:34:13.122093Z',
verified: false,
};
const supervisorUser = {
role: 'supervisor',
data: {
url: 'http://localhost:8001/api/users/8/',
username: 'Tutuplapak',
email: '',
is_staff: false,
student: {
id: 3,
user: {
url: 'http://localhost:8000/api/users/9/',
username: 'muhammad.reza42',
email: 'muhammad.reza42@ui.ac.id',
is_staff: false,
},
name: 'Muhammad R.',
created: '2017-03-28T13:33:46.147241Z',
updated: '2017-03-28T13:33:46.148248Z',
npm: 1406543593,
resume: null,
phone_number: null,
birth_place: null,
birth_date: null,
major: null,
batch: null,
show_resume: false,
bookmarked_vacancies: [
3,
2,
],
applied_vacancies: [
3,
1,
],
},
},
};
it('renders for verified without problem', () => {
const lowongan = ReactTestUtils.renderIntoDocument(
<AdminVacancy status={4} data={response} />);
expect(lowongan).to.exist;
});
it('renders for unverified without problem', () => {
const lowongan = ReactTestUtils.renderIntoDocument(
<AdminVacancy status={3} data={response2} />);
expect(lowongan).to.exist;
});
it('generate button without problem', () => {
const lowongan = ReactTestUtils.renderIntoDocument(
<AdminVacancy status={3} data={response2} />);
expect(lowongan.generateButton()).to.exist;
});
});
...@@ -34,6 +34,46 @@ describe('VacancyList', () => { ...@@ -34,6 +34,46 @@ describe('VacancyList', () => {
}, },
}; };
const supervisorUser = {
role: 'supervisor',
data: {
url: 'http://localhost:8001/api/users/8/',
username: 'Tutuplapak',
email: '',
is_staff: false,
company: null,
supervisor: {
id: 3,
user: {
url: 'http://localhost:8000/api/users/9/',
username: 'muhammad.reza42',
email: 'muhammad.reza42@ui.ac.id',
is_staff: false,
},
name: 'Muhammad R.',
created: '2017-03-28T13:33:46.147241Z',
updated: '2017-03-28T13:33:46.148248Z',
npm: 1406543593,
resume: null,
phone_number: null,
birth_place: null,
birth_date: null,
major: null,
batch: null,
show_resume: false,
bookmarked_vacancies: [
3,
2,
],
applied_vacancies: [
3,
1,
],
},
student: null,
},
};
const studentUser = { const studentUser = {
role: 'company', role: 'company',
data: { data: {
...@@ -245,6 +285,20 @@ describe('VacancyList', () => { ...@@ -245,6 +285,20 @@ describe('VacancyList', () => {
expect(vacancyList.generateVacancies()).to.exist; expect(vacancyList.generateVacancies()).to.exist;
}); });
it('renders without problem for supervisor', () => {
const vacancyList = ReactTestUtils.renderIntoDocument(
<VacancyList items={newResponse} userId={3} user={supervisorUser} />);
vacancyList.state.vacancies = newResponse;
expect(vacancyList.generateVacancies()).to.exist;
});
it('update status without problem', () => {
const vacancyList = ReactTestUtils.renderIntoDocument(
<VacancyList items={newResponse} userId={3} user={supervisorUser} />);
vacancyList.state.vacancies = newResponse;
vacancyList.updateStatus(4,1);
});
// it('renders with problem for company', () => { // it('renders with problem for company', () => {
// const vacancyList = ReactTestUtils.renderIntoDocument( // const vacancyList = ReactTestUtils.renderIntoDocument(
// <VacancyList type="company" userId={1} url="test" />); // <VacancyList type="company" userId={1} url="test" />);
......
import React from 'react';
import ReactTestUtils from 'react-addons-test-utils';
import VerifyAdminModal from '../../components/VerifyAdminModal';
import fetchMock from 'fetch-mock';
import Storage from '../../lib/Storage';
describe('VerifyAdminModal', () => {
it('renders without problem', () => {
const verifyModal = ReactTestUtils.renderIntoDocument(
<VerifyAdminModal />,
);
expect(verifyModal).to.exist;
});
it('open without problem', () => {
const verifyModal = ReactTestUtils.renderIntoDocument(
<VerifyAdminModal id={4} />);
const modal = ReactTestUtils.findRenderedDOMComponentWithTag(verifyModal, 'Button');
ReactTestUtils.Simulate.click(modal);
expect(verifyModal.state.modalOpen).to.equal(true);
});
it('close without problem', () => {
const verifyModal = ReactTestUtils.renderIntoDocument(
<VerifyAdminModal id={4} />);
verifyModal.handleClose();
expect(verifyModal.state.modalOpen).to.equal(false);
});
});
import React from 'react';
import { Item, Grid, Icon, Button } from 'semantic-ui-react';
import VerifyAdminModal from './VerifyAdminModal';
import Server from '../lib/Server';
export default class AdminVacancy extends React.Component {
static propTypes = {
data: React.PropTypes.object.isRequired,
updateStatus : React.PropTypes.func.isRequired,
};
changeVerifiedStatus(){
let data = {};
if(this.props.data.verified){
data = {"verified" : false};
}
else{
data = {"verified" : true};
}
Server.patch(`/vacancies/${this.props.data.id}/verify/`, data).then((status) => {
this.props.updateStatus(this.props.data.id, status.status);
});
}
generateButton(){
const unverifyButton = <Button floated="right" color="red" onClick={this.changeVerifiedStatus.bind(this)}>Batalkan Verifikasi</Button>;
const verifyButton = <Button floated="right" color="blue" onClick={this.changeVerifiedStatus.bind(this)}>Verifikasi</Button>;
if(this.props.data.verified){
return unverifyButton;
}
return verifyButton;
}
render() {
return (
<Item className="adminItems">
<Item.Image src="http://semantic-ui.com/images/wireframe/image.png" size="small" />
<Item.Content>
<Item.Header as="a">{this.props.data.name}</Item.Header>
<Grid.Row>
<Grid.Column floated="left">
<h4>{this.props.data.company.name} </h4>
{this.props.data.company.address}
</Grid.Column>
<Grid.Column floated="right">
{this.generateButton()}
</Grid.Column>
</Grid.Row>
</Item.Content>
</Item>
);
}
}
import React from 'react'; import React from 'react';
import { Menu, Image } from 'semantic-ui-react'; import { Menu, Image, Popup, Button, Card } from 'semantic-ui-react';
import { Link, browserHistory } from 'react-router'; import { Link, browserHistory } from 'react-router';
import Server from '../lib/Server'; import Server from '../lib/Server';
import Storage from '../lib/Storage'; import Storage from '../lib/Storage';
const defaultPicture = 'http://semantic-ui.com/images/avatar/small/elliot.jpg';
export default class TopMenu extends React.Component { export default class TopMenu extends React.Component {
static propTypes = { static propTypes = {
...@@ -14,6 +16,7 @@ export default class TopMenu extends React.Component { ...@@ -14,6 +16,7 @@ export default class TopMenu extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
/* istanbul ignore next */ /* istanbul ignore next */
console.log(this.props.user);
this.state = { activeItem: 'home' }; this.state = { activeItem: 'home' };
this.logout = this.logout.bind(this); this.logout = this.logout.bind(this);
this.logoutCompany = this.logoutCompany.bind(this); this.logoutCompany = this.logoutCompany.bind(this);
...@@ -39,6 +42,7 @@ export default class TopMenu extends React.Component { ...@@ -39,6 +42,7 @@ export default class TopMenu extends React.Component {
render() { render() {
const { activeItem } = this.state; const { activeItem } = this.state;
return ( return (
<div> <div>
{ this.props.user.data.is_staff && this.props.user.data.company && ( { this.props.user.data.is_staff && this.props.user.data.company && (
...@@ -48,13 +52,30 @@ export default class TopMenu extends React.Component { ...@@ -48,13 +52,30 @@ export default class TopMenu extends React.Component {
</div> </div>
)} )}
<Menu color="blue" pointing secondary> <Menu color="blue" pointing secondary>
<Image as="a" size="small" src="/assets/img/logo.png" href="/" /> <Image as="a" size="small" src="/assets/img/logo.png" href="/" />
<Menu.Menu position="right"> <Menu.Menu position="right">
<Menu.Item as={Link} to="/home" name="home" active={activeItem === 'home'} onClick={this.handleItemClick} /> <Menu.Item as={Link} to="/home" name="home" active={activeItem === 'home'} onClick={this.handleItemClick} />
<Menu.Item as={Link} to="/profile" name="profil" active={activeItem === 'profil'} onClick={this.handleItemClick} /> <Menu.Item>
<Menu.Item as={Link} onClick={this.logout} name="logout" /> <Popup
</Menu.Menu> trigger={<Image
</Menu> as={Link} to="/profil" src={this.props.user.data.photo || defaultPicture} avatar
onClick={this.handleItemClick}
/>}
flowing
hoverable
>
<Card
header={this.props.user.data.name}
description={this.props.user.data.email}
/>
<Button as={Link} onClick={this.logout} name="logout" color="blue" size="tiny">Logout</Button>
</Popup>
</Menu.Item>
</Menu.Menu>
</Menu>
</div> </div>
); );
} }
......
...@@ -3,6 +3,7 @@ import { Item, Button, Grid } from 'semantic-ui-react'; ...@@ -3,6 +3,7 @@ import { Item, Button, Grid } from 'semantic-ui-react';
import { Link } from 'react-router'; import { Link } from 'react-router';
import Vacancy from './Vacancy'; import Vacancy from './Vacancy';
import CompanyVacancy from './CompanyVacancy'; import CompanyVacancy from './CompanyVacancy';
import AdminVacancy from './AdminVacancy';
import Server from '../lib/Server'; import Server from '../lib/Server';
export default class VacancyList extends React.Component { export default class VacancyList extends React.Component {
...@@ -17,6 +18,15 @@ export default class VacancyList extends React.Component { ...@@ -17,6 +18,15 @@ export default class VacancyList extends React.Component {
items: [], items: [],
}; };
updateStatus(id, status) {
const obj = [];
this.state.vacancies.map((vacancy) => {
if (vacancy.id !== id) return obj.push(vacancy);
return null;
});
this.setState({ vacancies: obj });
}
constructor(props) { constructor(props) {
super(props); super(props);