From ec9e30c7df3a191abf77e4d1c64ae78be8393341 Mon Sep 17 00:00:00 2001 From: "M. Reza Qorib" <rezaqorib96@gmail.com> Date: Sun, 7 May 2017 19:17:04 +0700 Subject: [PATCH] [#144502159] [Green] #37 create Pagination component --- assets/js/VacancyPage.jsx | 13 ++- .../__test__/components/Pagination-test.jsx | 97 +++++++++++-------- assets/js/components/Pagination.jsx | 75 ++++++++++++++ kape/settings.py | 6 +- 4 files changed, 143 insertions(+), 48 deletions(-) create mode 100644 assets/js/components/Pagination.jsx diff --git a/assets/js/VacancyPage.jsx b/assets/js/VacancyPage.jsx index 438defe0..e7b1b8a6 100644 --- a/assets/js/VacancyPage.jsx +++ b/assets/js/VacancyPage.jsx @@ -2,6 +2,8 @@ import React from 'react'; import Tabs from './components/Tabs'; import Pane from './components/Pane'; import VacancyList from './components/VacancyList'; +import Pagination from './components/Pagination'; +import { Menu, Icon } from 'semantic-ui-react'; export default class VacancyPage extends React.Component { @@ -34,10 +36,15 @@ export default class VacancyPage extends React.Component { return ( <Tabs selected={0}> <Pane label="Semua Lowongan" > - <VacancyList - key={1} - userId={this.state.id} + <Pagination url="/vacancies/" + child={ + <VacancyList + key={1} + userId={this.state.id} + url="/vacancies/" + /> + } /> </Pane> <Pane label="Lamaran saya" > diff --git a/assets/js/__test__/components/Pagination-test.jsx b/assets/js/__test__/components/Pagination-test.jsx index 54804bfd..54dc9211 100644 --- a/assets/js/__test__/components/Pagination-test.jsx +++ b/assets/js/__test__/components/Pagination-test.jsx @@ -2,41 +2,44 @@ import React from 'react'; import ReactTestUtils from 'react-addons-test-utils'; import fetchMock from 'fetch-mock'; -import List from '../../components/Pagination' -import VacancyList from '../../components/VacancyList' +import Pagination from '../../components/Pagination'; describe('Pagination', () => { - 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 response = { + items: [{ + 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, + }, + ], + next:'/next', + }; const response2 = [{ close_time: '2019-03-28T05:55:42Z', @@ -67,26 +70,34 @@ describe('Pagination', () => { fetchMock.get('*', response); const pagination = ReactTestUtils.renderIntoDocument( <Pagination child={<div />} url="test" />); - pagination.getItemsData(); - expect(pagination.state.items).to.equal(response); + pagination.getItemsData().then(() => + expect(JSON.stringify(pagination.state.items)).to.equal(JSON.stringify(response.items))); + fetchMock.restore(); + }); + + it('renders without problem when failed getting data', () => { + fetchMock.get('*', 400); + const pagination = ReactTestUtils.renderIntoDocument( + <Pagination child={<div />} url="test" />); + expect(pagination).to.exist; fetchMock.restore(); }); - it('generate child components without problem', () => { + it('can go prev without problem', () => { fetchMock.get('*', response); - const child = <VacancyList url="" userId=""/> const pagination = ReactTestUtils.renderIntoDocument( - <Pagination child={child} url="test" />); - const childRendered = ReactTestUtils.findRenderedDOMComponentWithTag(pagination, child); - expect(childRendered).to,exist; + <Pagination child={<div />} url="test" />); + const prev = ReactTestUtils.scryRenderedDOMComponentsWithTag(pagination, 'a')[0]; + ReactTestUtils.Simulate.click(prev); fetchMock.restore(); }); - it('renders without problem when failed getting data', () => { - fetchMock.get('*', 400); + it('can go next without problem', () => { + fetchMock.get('*', response); const pagination = ReactTestUtils.renderIntoDocument( <Pagination child={<div />} url="test" />); - expect(pagination).to.exist; + const next = ReactTestUtils.scryRenderedDOMComponentsWithTag(pagination, 'a')[2]; + ReactTestUtils.Simulate.click(next); fetchMock.restore(); }); }); diff --git a/assets/js/components/Pagination.jsx b/assets/js/components/Pagination.jsx new file mode 100644 index 00000000..618706e9 --- /dev/null +++ b/assets/js/components/Pagination.jsx @@ -0,0 +1,75 @@ +import React from 'react'; +import { Menu, Container, Icon } from 'semantic-ui-react'; +import Server from '../lib/Server'; +import ModalAlert from '../components/ModalAlert'; + + +export default class Pagination extends React.Component { + + static propTypes = { + url: React.PropTypes.string.isRequired, + child: React.PropTypes.node.isRequired, + }; + + constructor(props) { + super(props); + /* istanbul ignore next */ + this.state = { + items: [], + current: 1, + next: '', + prev: '', + url: this.props.url, + }; + this.getItemsData = this.getItemsData.bind(this); + this.handleMovement = this.handleMovement.bind(this); + this.handleNext = this.handleNext.bind(this); + this.handlePrev = this.handlePrev.bind(this); + this.refresh = this.refresh.bind(this); + this.getItemsData(); + } + + getItemsData = () => Server.get(this.state.url, false).then((data) => { + this.setState({ items: data.items, next: data.next, prev: data.prev }); + }, error => error.then((r) => { + this.modalAlert.open('Gagal Mengambil Data', r.error); + })); + + refresh() { + this.forceUpdate(); + } + + handleMovement(dir) { + const newUrl = this.state[dir]; + this.setState({ url: newUrl }); + this.getItemsData(); + } + + handlePrev() { + this.handleMovement('prev'); + } + + handleNext() { + this.handleMovement('next'); + } + + render = () => ( + <div> + <ModalAlert ref={(modal) => { this.modalAlert = modal; }} /> + {this.props.child} + <Container textAlign="right"> + <Menu pagination icon="labeled" className="vacancyList"> + <Menu.Item name="prev" disabled={this.state.current !== 1} onClick={this.handlePrev}> + <span><Icon disabled={this.state.current !== 1} name="angle left" /></span> + </Menu.Item> + <Menu.Item name="current" active onClick={this.refresh}> + {this.state.current} + </Menu.Item> + <Menu.Item name="next" onClick={this.handleNext}> + <span><Icon name="angle right" /></span> + </Menu.Item> + </Menu> + </Container> + </div> + ); +} diff --git a/kape/settings.py b/kape/settings.py index 8fd0c2f2..7869e068 100755 --- a/kape/settings.py +++ b/kape/settings.py @@ -145,7 +145,9 @@ REST_FRAMEWORK = { # or allow read-only access for unauthenticated users. 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly' - ] + ], + 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', + 'PAGE_SIZE': 10 } GZIP_CONTENT_TYPES = ( @@ -159,5 +161,5 @@ SESSION_COOKIE_HTTPONLY = False RUNNING_DEVSERVER = (len(sys.argv) > 1 and sys.argv[1] == 'runserver') -API_CS_CREDENTIALS = {'user': 'lalala', 'password': 'lalala'} +API_CS_CREDENTIALS = {'user': 'kape', 'password': 'yukcarikape'} -- GitLab