From 8a177f53656743a9ba189eb43726a17dfefc807a Mon Sep 17 00:00:00 2001 From: "M. Reza Qorib" <rezaqorib96@gmail.com> Date: Wed, 24 May 2017 09:38:03 +0700 Subject: [PATCH] So much things done. Create SupervisorPage, refactor TopMenu and Dashboard, add and refactor many testing files. --- assets/js/Dashboard.jsx | 41 +------ assets/js/ProfilePage.jsx | 7 +- assets/js/SupervisorPage.jsx | 53 +++++++++ assets/js/VacancyPage.jsx | 3 +- assets/js/__test__/Dashboard-test.jsx | 23 +++- assets/js/__test__/SupervisorPage-test.jsx | 58 ++++++++++ assets/js/__test__/components/Footer-test.jsx | 12 ++ .../js/__test__/components/TopMenu-test.jsx | 23 +++- .../__test__/components/VacancyList-test.jsx | 103 ++++++++---------- assets/js/components/ApplicationList.jsx | 55 ++++++++++ assets/js/components/SupervisorPage.jsx | 63 ----------- assets/js/components/Tables.jsx | 45 -------- assets/js/components/TopMenu.jsx | 97 +++++++++++------ assets/js/index.jsx | 4 +- 14 files changed, 336 insertions(+), 251 deletions(-) create mode 100644 assets/js/SupervisorPage.jsx create mode 100644 assets/js/__test__/SupervisorPage-test.jsx create mode 100644 assets/js/__test__/components/Footer-test.jsx create mode 100644 assets/js/components/ApplicationList.jsx delete mode 100644 assets/js/components/SupervisorPage.jsx delete mode 100644 assets/js/components/Tables.jsx diff --git a/assets/js/Dashboard.jsx b/assets/js/Dashboard.jsx index c5d95563..14b2e341 100755 --- a/assets/js/Dashboard.jsx +++ b/assets/js/Dashboard.jsx @@ -1,9 +1,6 @@ import React from 'react'; import TopMenu from './components/TopMenu'; -import Server from './lib/Server'; - - -const defaultPicture = 'http://semantic-ui.com/images/avatar/small/elliot.jpg'; +import Footer from './components/Footer'; export default class Dashboard extends React.Component { static propTypes = { @@ -16,43 +13,9 @@ export default class Dashboard extends React.Component { ]).isRequired, }; - static getInfo(user) { - const adminRole = { - name: 'admin', - user: { - email: '', - }, - photo: null, - }; - const role = user.role; - if (role === 'student') { - return user.data.student; - } else if (role === 'company') { - return user.data.company; - } - - return adminRole; - } - - constructor(props) { - super(props); - /* istanbul ignore next */ - const data = Dashboard.getInfo(this.props.user); - this.state = { - id: data.id, - name: data.name, - email: data.user.email, - photo: data.photo, - }; - } - - render = () => ( <div> - <TopMenu - name={this.state.name} email={this.state.email} - photo={this.state.photo ? this.state.photo : defaultPicture} - /> + <TopMenu user={this.props.user} /> {this.props.children} </div> ) diff --git a/assets/js/ProfilePage.jsx b/assets/js/ProfilePage.jsx index 2700b8ac..564e2867 100644 --- a/assets/js/ProfilePage.jsx +++ b/assets/js/ProfilePage.jsx @@ -157,7 +157,7 @@ export default class ProfilePage extends React.Component { <Grid.Column width={7}> <Header as="h2" icon textAlign="center"> <br /> - <Image src={this.state.photo ? this.state.photo : defaultPicture} size="medium" /> + <Image src={this.state.photo || defaultPicture} size="medium" /> </Header> </Grid.Column> @@ -219,10 +219,7 @@ export default class ProfilePage extends React.Component { <Container textAlign="center"> <div className="button-profile"> - <a href={this.state.resume ? this.state.resume : '#'} ><Button primary size="small">Resume</Button></a> - { this.state.show_transcript && - <Button primary size="small">Transkrip</Button> - } + <a href={this.state.resume || '#'} ><Button primary size="small">Resume</Button></a> </div> <div> <h4> Bagikan Transkrip : { this.state.bagikanTranskrip }</h4> diff --git a/assets/js/SupervisorPage.jsx b/assets/js/SupervisorPage.jsx new file mode 100644 index 00000000..4d4fe749 --- /dev/null +++ b/assets/js/SupervisorPage.jsx @@ -0,0 +1,53 @@ +import React from 'react'; +import { Header, Icon, Grid } from 'semantic-ui-react'; +import Pagination from './components/Pagination'; +import Server from './lib/Server'; +import ApplicationList from './components/ApplicationList'; + +const cols = [ + { key: 'StudentName', label: 'Nama' }, + { key: 'StudentID', label: 'NPM' }, + { key: 'Perusahaan', label: 'Perusahaan' }, + { key: 'Posisi', label: 'Posisi' }, + { key: 'Status', label: 'Status' }, +]; + +export default class SupervisorPage extends React.Component { + + constructor(props) { + super(props); + /* istanbul ignore next */ + this.state = { list: [] }; + } + + componentDidMount() { + this.UserList(); + } + + UserList() { + Server.get('/student-applications/', false).then((data) => { + this.setState({ list: data.results }); + }); + } + + render = () => { + return ( + <Grid container columns="eleven" doubling> + <Grid.Row> + <br /> + </Grid.Row> + <Grid.Row> + <Header as="h2"> + <Icon name="list" /> + Daftar Mahasiswa + </Header> + </Grid.Row> + <Grid.Row> + <div id="layout-content" className="layout-content-wrapper"> + <Pagination url={'/student-applications/'} child={<ApplicationList cols={cols} />} /> + </div> + </Grid.Row> + </Grid> + ); + } +} diff --git a/assets/js/VacancyPage.jsx b/assets/js/VacancyPage.jsx index 2201e5b3..2032db0e 100644 --- a/assets/js/VacancyPage.jsx +++ b/assets/js/VacancyPage.jsx @@ -3,7 +3,7 @@ import Tabs from './components/Tabs'; import Pane from './components/Pane'; import VacancyList from './components/VacancyList'; import Pagination from './components/Pagination'; -import Applicants from './components/SupervisorPage'; +import Applicants from './SupervisorPage'; export default class VacancyPage extends React.Component { @@ -47,7 +47,6 @@ export default class VacancyPage extends React.Component { /> } /> - <Applicants /> </Pane> <Pane label="Lamaran saya" > <Pagination diff --git a/assets/js/__test__/Dashboard-test.jsx b/assets/js/__test__/Dashboard-test.jsx index 892fbabf..1e01baf0 100644 --- a/assets/js/__test__/Dashboard-test.jsx +++ b/assets/js/__test__/Dashboard-test.jsx @@ -90,7 +90,28 @@ describe('Dashboard', () => { email: '', is_staff: false, company: null, - supervisor: 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, + bookmarked_vacancies: [ + 3, + ], + applied_vacancies: [ + 3, + 1, + ], + }, student: null, }, }; diff --git a/assets/js/__test__/SupervisorPage-test.jsx b/assets/js/__test__/SupervisorPage-test.jsx new file mode 100644 index 00000000..b2c7de81 --- /dev/null +++ b/assets/js/__test__/SupervisorPage-test.jsx @@ -0,0 +1,58 @@ +import React from 'react'; +import ReactTestUtils from 'react-addons-test-utils'; +import fetchMock from 'fetch-mock'; +import SupervisorPage from '../SupervisorPage'; + +describe('SupervisorPage', () => { + const data = { + count: 5, + next: null, + previous: null, + results: [ + { + company_name: 'Tutuplapak', + name: 'Joshua Casey Darian Gunawan', + npm: 1406622616, + vacancy_name: 'Software Engineer', + status: 'accepted', + }, + { + company_name: 'Tutuplapak', + name: 'Muhammad Reza Qorib', + npm: 1406543593, + vacancy_name: 'Software Engineer', + status: 'accepted', + }, + { + company_name: 'Tutuplapak', + name: 'Muhammad Reza Qorib', + npm: 1406543593, + vacancy_name: 'Kepala Sekolah', + status: 'read', + }, + { + company_name: 'company1', + name: 'Farhan Farasdak', + npm: 1406572321, + vacancy_name: 'Data Scientist', + status: 'new', + }, + { + company_name: 'company1', + name: 'student2', + npm: 1406527513, + vacancy_name: 'Data Scientist', + status: 'new', + }, + ], + }; + + fetchMock.get('*', data); + + it('renders for admin without problem', () => { + const supervisorPage = ReactTestUtils.renderIntoDocument( + <SupervisorPage />); + expect(supervisorPage).to.exist; + fetchMock.restore(); + }); +}); diff --git a/assets/js/__test__/components/Footer-test.jsx b/assets/js/__test__/components/Footer-test.jsx new file mode 100644 index 00000000..d6cb3ee9 --- /dev/null +++ b/assets/js/__test__/components/Footer-test.jsx @@ -0,0 +1,12 @@ +import React from 'react'; +import ReactTestUtils from 'react-addons-test-utils'; +import Footer from '../../components/Footer'; + +describe('Footer', () => { + + it('renders without problem', () => { + const footer = ReactTestUtils.renderIntoDocument( + <Footer params={{ id: 1 }} />); + expect(footer).to.exist; + }); +}); diff --git a/assets/js/__test__/components/TopMenu-test.jsx b/assets/js/__test__/components/TopMenu-test.jsx index 7f841e10..b3398263 100644 --- a/assets/js/__test__/components/TopMenu-test.jsx +++ b/assets/js/__test__/components/TopMenu-test.jsx @@ -119,7 +119,28 @@ describe('TopMenu', () => { email: '', is_staff: false, company: null, - supervisor: 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, + bookmarked_vacancies: [ + 3, + ], + applied_vacancies: [ + 3, + 1, + ], + }, student: null, }, }; diff --git a/assets/js/__test__/components/VacancyList-test.jsx b/assets/js/__test__/components/VacancyList-test.jsx index ee03b113..37389b29 100644 --- a/assets/js/__test__/components/VacancyList-test.jsx +++ b/assets/js/__test__/components/VacancyList-test.jsx @@ -35,7 +35,7 @@ describe('VacancyList', () => { }; const studentUser = { - role: 'company', + role: 'student', data: { url: 'http://localhost:8001/api/users/8/', username: 'Tutuplapak', @@ -69,6 +69,8 @@ describe('VacancyList', () => { 1, ], }, + company: null, + supervisor: null, }, }; @@ -215,6 +217,38 @@ describe('VacancyList', () => { }, ]; + 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: 1, + name: 'Software Engineer', + open_time: '2017-03-28T05:55:38Z', + updated: '2017-03-28T07:34:13.122093Z', + verified: true, + }, { + close_time: '2019-03-28T05:55:42Z', + company: { + address: 'kebayoran baru', + id: 2, + logo: null, + name: 'tutup lapak', + }, + created: '2017-03-28T07:05:47.128672Z', + description: 'Lorem ipsum dolbh.', + id: 2, + 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: { @@ -235,96 +269,45 @@ describe('VacancyList', () => { it('renders without problem', () => { const vacancyList = ReactTestUtils.renderIntoDocument( <VacancyList items={newResponse} userId={1} user={studentUser} />); + vacancyList.generateVacancies(); expect(vacancyList).to.exist; }); it('renders without problem for company', () => { const vacancyList = ReactTestUtils.renderIntoDocument( <VacancyList items={newResponse} userId={1} user={companyUser} />); + vacancyList.generateVacancies(); vacancyList.state.vacancies = newResponse; expect(vacancyList.generateVacancies()).to.exist; }); - // it('renders with problem for company', () => { - // const vacancyList = ReactTestUtils.renderIntoDocument( - // <VacancyList type="company" userId={1} url="test" />); - // vacancyList.state.vacancies = response; - // expect(vacancyList.generateVacancies()).to.exist; - // }); - // - // it('update bookmarks without problem', () => { - // const vacancyList = ReactTestUtils.renderIntoDocument( - // <VacancyList userId={1} url="test" />); - // vacancyList.state.appliedList = [{ id: 1 }, { id: 3 }]; - // vacancyList.updateStatusList().then(() => { - // expect(JSON.stringify(vacancyList.state.bookmarkList)).to.be.defined; - // }); - // }); - // - // it('check applied vacancies without problem', () => { - // const vacancyList = ReactTestUtils.renderIntoDocument( - // <VacancyList userId={1} url="test" />); - // vacancyList.updateStatusList().then(() => { - // expect(JSON.stringify(vacancyList.state.bookmarkList)).to.be.defined; - // }); - // }); - // - // it('renders marked bookmarked vacancies without problem', (done) => { - // const vacancyList = ReactTestUtils.renderIntoDocument( - // <VacancyList userId={1} url="test" />); - // vacancyList.state.vacancies = response; - // vacancyList.state.bookmarkList = [{ id: 5 }, { id: 3 }, { id: 1 }]; - // vacancyList.updateStatusList().then(() => { - // expect(vacancyList.generateVacancies()).to.exist; - // done(); - // }, () => done()); - // }); - // - // it('renders not marked vacancies without problem', () => { - // fetchMock.get('*', response); - // const vacancyList = ReactTestUtils.renderIntoDocument( - // <VacancyList userId={1} url="test" />); - // vacancyList.state.vacancies = response; - // vacancyList.state.bookmarkList = [{ id: 6 }, { id: 4 }, { id: 2 }]; - // expect(vacancyList.generateVacancies()).to.exist; - // fetchMock.restore(); - // }); - // - // it('success calling API', () => { - // fetchMock.get('*', response); - // const vacancyList = ReactTestUtils.renderIntoDocument( - // <VacancyList userId={1} url="test" />); - // vacancyList.state.vacancies = response; - // expect(JSON.stringify(vacancyList.state.vacancies)).to.equal(JSON.stringify(response)); - // fetchMock.restore(); - // }); - // it('success delete vacancy', () => { fetchMock.restore(); fetchMock.delete('*', response2); + fetchMock.get('*', newResponse); const vacancyList = ReactTestUtils.renderIntoDocument( - <VacancyList userId={1} url="test" deleteCallback={() => {}} user={companyUser} />); + <VacancyList items={newResponse} userId={1} deleteCallback={() => {}} user={companyUser} />); vacancyList.state.vacancies = newResponse; vacancyList.deleteVacancy(1).then(() => { - expect(JSON.stringify(vacancyList.state.vacancies)).to.equal(JSON.stringify(response)); + expect(JSON.stringify(vacancyList.state.vacancies)).to.equal(JSON.stringify(newResponse)); fetchMock.restore(); }, () => { fetchMock.restore(); }); }); - it('fails delete vacancy', () => { + it('fails delete vacancy', (done) => { fetchMock.restore(); fetchMock.delete('*', 404); const vacancyList = ReactTestUtils.renderIntoDocument( <VacancyList userId={1} items={newResponse} user={companyUser} deleteCallback={() => {}} />, ); - vacancyList.state.vacancies = newResponse; + vacancyList.state.vacancies = response; vacancyList.deleteVacancy(1).then(() => { fetchMock.restore(); done(); }, () => { - expect(JSON.stringify(vacancyList.state.vacancies)).to.equal(JSON.stringify(newResponse)); + expect(JSON.stringify(vacancyList.state.vacancies)).to.equal(JSON.stringify(response)); fetchMock.restore(); done(); }); diff --git a/assets/js/components/ApplicationList.jsx b/assets/js/components/ApplicationList.jsx new file mode 100644 index 00000000..bf2decbd --- /dev/null +++ b/assets/js/components/ApplicationList.jsx @@ -0,0 +1,55 @@ +import React from 'react'; +import { Table } from 'semantic-ui-react'; + +export default class ApplicationList extends React.Component { + static propTypes = { + cols: React.PropTypes.any.isRequired, + items: React.PropTypes.any, + }; + + static defaultProps = { + items: [], + }; + + generateHeaders() { + const cols2 = this.props.cols; // [{key, label}] + + // generate our header (th) cell components + return cols2.map(colData => + <Table.HeaderCell singleLine key={colData.key}> {colData.label} </Table.HeaderCell> + ); + } + + generateRows() { + return this.props.items.map(item => + ( + <Table.Row key={`${item.npm}_${item.company}_${item.position}_${item.status}_row`}> + <Table.Cell key={`${item.name}_name`}> {item.name} </Table.Cell> + <Table.Cell key={`${item.name}_npm`}> {item.npm} </Table.Cell> + <Table.Cell key={`${item.name}_company`}> + {item.company_name} + </Table.Cell> + <Table.Cell key={`${item.name}_position`}> + {item.vacancy_name} + </Table.Cell> + <Table.Cell key={`${item.name}_status`}> + {item.status} + </Table.Cell> + </Table.Row> + ) + ); + } + + render() { + return ( + <Table celled padded> + <Table.Header > + <Table.Row> + {this.generateHeaders()} + </Table.Row> + </Table.Header> + <Table.Body>{this.generateRows()}</Table.Body> + </Table> + ); + } +} diff --git a/assets/js/components/SupervisorPage.jsx b/assets/js/components/SupervisorPage.jsx deleted file mode 100644 index ad2062ce..00000000 --- a/assets/js/components/SupervisorPage.jsx +++ /dev/null @@ -1,63 +0,0 @@ -import React from 'react'; -import { Header, Icon } from 'semantic-ui-react'; -import Tables from './Tables'; -import Server from '../lib/Server'; - -const cols = [ - { key: 'StudentName', label: 'Students Name' }, - { key: 'Perusahaan', label: 'Perusahaan' }, - { key: 'Posisi', label: 'Posisi' }, - { key: 'Status', label: 'Status' }, -]; - -const data2 = [ - { id: 1, StudentName: 'John Doe', Perusahaan: 'Jalanloka', Posisi: 'Software Engineer', Status: 'Melamar' }, - { id: 2, StudentName: 'Clark Kent', Perusahaan: 'Tutuplapak', Posisi: 'Data Scientist', Status: 'Diterima' }, - { id: 3, StudentName: 'Rosamund Pike', Perusahaan: 'Tutuplapak', Posisi: 'System Analyst', Status: 'Diterima' }, - { id: 4, StudentName: 'Melissa Benoist', Perusahaan: 'Blabla', Posisi: 'Data Scientist', Status: 'Melamar' }, -]; - - -export default class Applicants extends React.Component { - - constructor(props) { - super(props); - - this.state = { list: [] }; - } - - componentDidMount() { - this.UserList(); - } - - UserList() { - Server.get('/student-applications/', false).then((data) => { - this.setState({ list: data.results }); - }); - } - - render() { - const list = this.state.list.map((item, i) => <div> - <h1>{item.name}</h1> - <span>{item.npm}, {item.email}</span> - </div>); - return ( - - <div className="home-dosen"> - <Header as="h2"> - <Icon name="list" /> - <Header.Content> - Daftar Mahasiswa - </Header.Content> - </Header> - - - <div id="layout-content" className="layout-content-wrapper"> - <Tables cols={cols} data={data2} /> - <div className="panel-list">{ list }</div> - </div> - </div> - - ); - } -} diff --git a/assets/js/components/Tables.jsx b/assets/js/components/Tables.jsx deleted file mode 100644 index 8d56cfa5..00000000 --- a/assets/js/components/Tables.jsx +++ /dev/null @@ -1,45 +0,0 @@ -import React from 'react'; -import { Table } from 'semantic-ui-react'; - -export default class Tables extends React.Component { - static propTypes = { - cols: React.PropTypes.any.isRequired, - data: React.PropTypes.any.isRequired, - }; - - generateHeaders() { - const cols2 = this.props.cols; // [{key, label}] - - // generate our header (th) cell components - return cols2.map(colData => <Table.HeaderCell singleLine key={colData.key}> {colData.label} </Table.HeaderCell> - , error => error.then(() => ('Gagal mendapatkan informasi data')), - ); - } - - - generateRows() { - const cols3 = this.props.cols; // [{key, label}] - const data2 = this.props.data; - - return data2.map((item) => { - // handle the column data within each row - const cells = cols3.map(colData => - // colData.key might be "firstName" - <Table.Cell> {item[colData.key]} </Table.Cell>); - return <Table.Row key={item.id}> {cells} </Table.Row>; - }); - } - - render() { - return ( - <Table celled padded> - <Table.Header > - <Table.Row> - {this.generateHeaders()} - </Table.Row> - </Table.Header> - <Table.Body>{this.generateRows()}</Table.Body> - </Table> - ); - } -} diff --git a/assets/js/components/TopMenu.jsx b/assets/js/components/TopMenu.jsx index b5bc1f27..b3662174 100644 --- a/assets/js/components/TopMenu.jsx +++ b/assets/js/components/TopMenu.jsx @@ -4,67 +4,96 @@ import { Link, browserHistory } from 'react-router'; import Server from '../lib/Server'; import Storage from '../lib/Storage'; -const defaultImage = 'http://semantic-ui.com/images/avatar/small/elliot.jpg'; +const defaultPicture = 'http://semantic-ui.com/images/avatar/small/elliot.jpg'; export default class TopMenu extends React.Component { + static getInfo(user) { + const adminRole = { + name: 'admin', + user: { + email: '', + }, + photo: null, + }; + const role = user.role; + if (role === 'student') { + return user.data.student; + } else if (role === 'company') { + return user.data.company; + } else if (role === 'supervisor') { + return user.data.supervisor; + } + + return adminRole; + } + static propTypes = { - // user: React.PropTypes.object.isRequired, - name: React.PropTypes.string.isRequired, - email: React.PropTypes.string.isRequired, - photo: React.PropTypes.any.isRequired, + user: React.PropTypes.object.isRequired, }; constructor(props) { super(props); /* istanbul ignore next */ - // console.log(this.props.user); this.state = { activeItem: 'home' }; this.logout = this.logout.bind(this); + this.logoutCompany = this.logoutCompany.bind(this); } handleItemClick = (e, { name }) => this.setState({ activeItem: name }); - logout = () => { + logout = (e) => { + e.preventDefault(); Server.get('/api-auth/logout/?next=/', true).then(() => { Storage.clear(); browserHistory.push('/login'); }); }; - + logoutCompany = /* istanbul ignore next */ (e) => { + e.preventDefault(); + const userData = Storage.get('user-data'); + userData.company = null; + Storage.set('user-data', userData); + window.location.replace('/home'); + }; render() { const { activeItem } = this.state; - + const data = TopMenu.getInfo(this.props.user); return ( - <Menu color="blue" pointing secondary> - <Image as="a" size="small" src="/assets/img/logo.png" href="/" /> - <Menu.Menu position="right"> - <Menu.Item as={Link} to="/home" name="home" active={activeItem === 'home'} onClick={this.handleItemClick} /> - <Menu.Item as={Link} to="/profil" name="profile" onClick={this.handleItemClick} /> - <Menu.Item> - <Popup - trigger={<Image - as={Link} to="/profil" - src={this.props.photo ? this.props.photo : defaultImage} avatar - onClick={this.handleItemClick} - />} - flowing - hoverable - > - - <Card - header={this.props.name} - description={this.props.email} - /> - <Button as={Link} onClick={this.logout} name="logout" color="blue" size="tiny">Logout</Button> + <div> + { this.props.user.data.is_staff && this.props.user.data.company && ( + <div className="admin-bar"> + Anda login sebagai perusahaan: {this.props.user.data.company.name} (#{this.props.user.data.company.id}). + Untuk keluar, silahkan klik <a href="#" onClick={this.logoutCompany}> link ini</a> + </div> + )} + <Menu color="blue" pointing secondary> + <Image as="a" size="small" src="/assets/img/logo.png" href="/" /> + <Menu.Menu position="right"> + <Menu.Item as={Link} to="/home" name="home" active={activeItem === 'home'} onClick={this.handleItemClick} /> + <Menu.Item> + <Popup + trigger={<Image + as={Link} to="/profil" src={data.photo || defaultPicture} avatar + onClick={this.handleItemClick} + />} + flowing + hoverable + > + <Card + header={data.name} + description={data.user.email} + /> + <Button as={Link} onClick={this.logout} name="logout" color="blue" size="tiny">Logout</Button> - </Popup> + </Popup> - </Menu.Item> - </Menu.Menu> - </Menu> + </Menu.Item> + </Menu.Menu> + </Menu> + </div> ); } } diff --git a/assets/js/index.jsx b/assets/js/index.jsx index 625b87d6..218b6933 100644 --- a/assets/js/index.jsx +++ b/assets/js/index.jsx @@ -13,6 +13,7 @@ import ApplicantPage from './ApplicantPage'; import TranscriptPage from './TranscriptPage'; import AdminVacancyPage from './AdminVacancyPage'; import CompanyPage from './CompanyPage'; +import SupervisorPage from './SupervisorPage' export default class App extends React.Component { @@ -91,7 +92,7 @@ export default class App extends React.Component { render() { const staff = this.authorization(['admin']); const student = this.authorization(['admin', 'student']); - // const supervisor = this.authorization(['admin', 'supervisor']); + const supervisor = this.authorization(['admin', 'supervisor']); const company = this.authorization(['admin', 'company']); const commonUser = this.authorization(['admin', 'student', 'company']); const grownups = this.authorization(['admin', 'company', 'supervisor']); @@ -112,6 +113,7 @@ export default class App extends React.Component { <Route path="/mahasiswa/:id" component={grownups(ProfilePage)} /> <Route path="/perusahaan/:id" component={facultyMember(CompanyProfile)} /> <Route path="/perusahaan" component={staff(CompanyPage)} /> + <Route path="/rekap" component={supervisor(SupervisorPage)} /> <Route path="/transkrip/:id" component={facultyMember(CompanyProfile)} /> </Route> <Route path="/home" onEnter={this.handleHome} /> -- GitLab