diff --git a/.gitignore b/.gitignore index 2c6cae6466efa0b98f94cfdcec948ab8ae135093..f162fc7d1cfac461e330b5c0aa39cd0d98afe3c0 100755 --- a/.gitignore +++ b/.gitignore @@ -319,3 +319,6 @@ webpack-stats.json assets/bundles/* test/* .tmp/ + +# MacOS related files +.DS_Store diff --git a/assets/js/__test__/components/Vacancy-test.jsx b/assets/js/__test__/components/Vacancy-test.jsx index bfb44832032dcfafb5e886ebd3987af79029b750..f99e6de68466447ddbd3be765acb91305f90b8a3 100644 --- a/assets/js/__test__/components/Vacancy-test.jsx +++ b/assets/js/__test__/components/Vacancy-test.jsx @@ -18,7 +18,7 @@ describe('Vacancy', () => { created: '2017-03-28T07:05:47.128672Z', description: 'Lorem ipsum dolbh.', id: 3, - name: 'Software Engineer', + name: 'Software Engineer', open_time: '2017-03-28T05:55:38Z', updated: '2017-03-28T07:34:13.122093Z', verified: true, @@ -131,6 +131,7 @@ describe('Vacancy', () => { it('cancel bookmarks without problem', () => { fetchMock.delete('*', { data: 'value' }); + fetchMock.get('*', { count: 'value' }); const lowongan = ReactTestUtils.renderIntoDocument( <Vacancy status="Daftar" user={studentUser} data={response2} bookmarked={1} />); const response3 = { student: { id: 1, name: 2 } }; @@ -145,6 +146,7 @@ describe('Vacancy', () => { it('cancel bookmarks with problem', () => { fetchMock.delete('*', 404); + fetchMock.get('*', { count: 'value' }); const lowongan = ReactTestUtils.renderIntoDocument( <Vacancy status="Daftar" user={studentUser} data={response2} bookmarked={1} />); const response3 = { student: { id: 1, name: 2 } }; diff --git a/assets/js/components/Vacancy.jsx b/assets/js/components/Vacancy.jsx index 3951c2ff8c94f4a36325e68510073ae718240bc9..48371bc76d6b4c18c1833e5080cec385e0ede10a 100644 --- a/assets/js/components/Vacancy.jsx +++ b/assets/js/components/Vacancy.jsx @@ -41,6 +41,7 @@ export default class Vacancy extends React.Component { deleteLoading: false, }; moment.locale('id'); + this.count(); this.bookmark = this.bookmark.bind(this); this.updateStatus = this.updateStatus.bind(this); this.generateAction = this.generateAction.bind(this); @@ -48,6 +49,12 @@ export default class Vacancy extends React.Component { this.removeVacancyApplication = this.removeVacancyApplication.bind(this); } + count() { + Server.get(`/applications/${this.props.data.id}/count/`, false).then((data) => { + this.setState({ count: data.count }); + }); + } + bookmark() { const data = { vacancy_id: this.props.data.id }; if (this.state.bookmarked < 1) { @@ -125,8 +132,10 @@ export default class Vacancy extends React.Component { <Grid.Column floated="left"> <h4>{ this.props.data.name }</h4> { this.props.data.company.name }<br /> - { this.props.data.company.address }<br /><br /> - Rp. { this.props.data.salary } <br /> <br /> + { this.props.data.company.address }<br /> + { this.state.count } orang telah mendaftar!<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> </Grid.Column> <Grid.Column floated="right" > diff --git a/core/migrations/0029_merge_20191008_1146.py b/core/migrations/0029_merge_20191008_1146.py new file mode 100644 index 0000000000000000000000000000000000000000..f6ee5c73975a155b2b2ebfef565c05f24f3caca8 --- /dev/null +++ b/core/migrations/0029_merge_20191008_1146.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.5 on 2019-10-08 04:46 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0028_merge_20191008_0843'), + ('core', '0028_merge_20191008_0921'), + ] + + operations = [ + ] diff --git a/core/tests/test_vacancies.py b/core/tests/test_vacancies.py index 3920ba472abc5d462f3d391715f6d748e7e521b2..9eb3d635be0c2de238cf933c7ff2ed3aab7abdf3 100644 --- a/core/tests/test_vacancies.py +++ b/core/tests/test_vacancies.py @@ -115,6 +115,49 @@ class ApplicationTests(APITestCase): response = self.client.delete(url) self.assertEqual(response.status_code, status.HTTP_200_OK) + def test_count_application_a_person_is_already_register(self): + new_user = User.objects.create_user('dummy.company', 'dummy.company@company.com', 'lalala123') + new_user2 = User.objects.create_user('dummy.student', 'dummy.student@student.com', 'lalala123') + + self.client.force_authenticate(new_user) + self.client.force_authenticate(new_user2) + + new_company = Company.objects.create(user=new_user, description="lalala", status=Company.VERIFIED, logo=None, + address=None) + new_student = Student.objects.create(user=new_user2, npm=1234123412) + + new_vacancy = Vacancy.objects.create(company=new_company, verified=True, open_time=datetime.fromtimestamp(0), + description="lalala", close_time=datetime.today()) + + application = Application.objects.create(student=new_student, vacancy=new_vacancy, cover_letter="lorem ipsum") + + url = '/api/applications/' + str(new_vacancy.pk) + '/count/' + + response = self.client.get(url, format='json') + + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.json()['count'], 1) + + def test_count_application_nobody_register(self): + new_user = User.objects.create_user('dummy.company', 'dummy.company@company.com', 'lalala123') + new_user2 = User.objects.create_user('dummy.student', 'dummy.student@student.com', 'lalala123') + + self.client.force_authenticate(new_user) + self.client.force_authenticate(new_user2) + + new_company = Company.objects.create(user=new_user, description="lalala", status=Company.VERIFIED, logo=None, + address=None) + new_student = Student.objects.create(user=new_user2, npm=1234123412) + new_vacancy = Vacancy.objects.create(company=new_company, verified=True, open_time=datetime.fromtimestamp(0), + description="lalala", close_time=datetime.today()) + + url = '/api/applications/' + str(new_vacancy.pk) + '/count/' + + response = self.client.get(url, format='json') + + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.json()['count'], 0) + @requests_mock.Mocker() def test_cannot_create_application_if_vacancy_is_closed(self, m): m.get('https://akun.cs.ui.ac.id/oauth/token/verify/?client_id=X3zNkFmepkdA47ASNMDZRX3Z9gqSU1Lwywu5WepG', json={"username": 'dummy.mahasiswa', "role": 'mahasiswa', "identity_number": '1234567890'}, status_code=200) @@ -404,7 +447,7 @@ class VacancyTest(APITestCase): superuser = User.objects.create_superuser('dummy.company', 'dummy.company@company.com', 'lalala123') new_company = Company.objects.create(user=superuser, description="lalalaz", status=Company.VERIFIED, logo=None, address=None) - + new_vacancy = Vacancy.objects.create(company=new_company, verified=True, open_time=datetime.fromtimestamp(0), description="lalala", close_time=timezone.now() - timedelta(minutes = 10)) self.client.force_authenticate(user=superuser) @@ -417,7 +460,7 @@ class VacancyTest(APITestCase): superuser = User.objects.create_superuser('dummy.company', 'dummy.company@company.com', 'lalala123') new_company = Company.objects.create(user=superuser, description="lalalaz", status=Company.VERIFIED, logo=None, address=None) - + new_vacancy = Vacancy.objects.create(company=new_company, verified=True, open_time=datetime.fromtimestamp(0), description="lalala", close_time=timezone.now() + timedelta(minutes = 10)) self.client.force_authenticate(user=superuser) diff --git a/core/views/vacancies.py b/core/views/vacancies.py index eb091acb29dfaab6c97dff459d27b258fd07d940..83e446fe3f248af41e22fa9a5eb9930c2cce583f 100644 --- a/core/views/vacancies.py +++ b/core/views/vacancies.py @@ -157,6 +157,11 @@ class ApplicationViewSet(MultiSerializerViewSetMixin, viewsets.GenericViewSet): serializer(applications, many=True, context={'request': request}).data) return Response(serializer(applications, many=True, context={'request': request}).data) + @detail_route(methods=['get'], permission_classes=[IsAdminOrStudent]) + def count(self, request, pk=None): + count = Application.objects.filter(vacancy_id=pk).count() + return Response({"count": count}, status=status.HTTP_200_OK) + def partial_update(self, request, pk=None): application = self.get_object() serializer = self.get_serializer_class()(application, data=request.data, partial=True) diff --git a/files/student-ui-ux-portofolio/a0263aa9-bc94-4577-9128-cf71cd0f41f7.pdf b/files/student-ui-ux-portofolio/a0263aa9-bc94-4577-9128-cf71cd0f41f7.pdf new file mode 100644 index 0000000000000000000000000000000000000000..379cb93fd41385e7ea21e9f02d44b2fb84fd860d Binary files /dev/null and b/files/student-ui-ux-portofolio/a0263aa9-bc94-4577-9128-cf71cd0f41f7.pdf differ diff --git a/files/student-ui-ux-portofolio/e47bb57f-1249-4393-9ab5-73e08712efdd.pdf b/files/student-ui-ux-portofolio/e47bb57f-1249-4393-9ab5-73e08712efdd.pdf new file mode 100644 index 0000000000000000000000000000000000000000..379cb93fd41385e7ea21e9f02d44b2fb84fd860d Binary files /dev/null and b/files/student-ui-ux-portofolio/e47bb57f-1249-4393-9ab5-73e08712efdd.pdf differ diff --git a/kape/settings.py b/kape/settings.py index 7529209fcc26179972d10cd9895de5eaabf98988..15257f0403ec50a6ca1b32cf9eb021696fb49f1b 100755 --- a/kape/settings.py +++ b/kape/settings.py @@ -159,7 +159,7 @@ USE_TZ = True STATIC_URL = '/assets/' STATIC_ROOT = '/home/kape/assets' MEDIA_URL = '/files/' -MEDIA_ROOT = '/home/kape/files' +MEDIA_ROOT = '/Users/kianutamaradianur/Documents/Universitas Indonesia/Semester 7/PMPL/kape/files' REST_FRAMEWORK = { # Use Django's standard `django.contrib.auth` permissions,