Fakultas Ilmu Komputer UI

Commit e9608ee6 authored by Ilham Darmawan Candra Purnama's avatar Ilham Darmawan Candra Purnama
Browse files

Fitur Pencarian untuk Lowongan, Daftar Lamaran, dan Bookmark

parent 08286292
......@@ -290,3 +290,26 @@ card .formRegis{
.ui.segment.kop {
line-height: 5px;
}
.search-container {
width: fit-content;
margin: auto;
}
.search-form {
border: none;
border-bottom: solid #0d5aa7 2px;
text-decoration: none;
outline: none;
font-size: 14pt;
}
.search-button {
background-color: #0d5aa7;
color: white;
border: none;
padding: 10px;
font-size: 14pt;
border-radius: 5px;
margin-left: 10px;
}
\ No newline at end of file
......@@ -2,6 +2,7 @@ import React from 'react';
import { Menu, Container, Icon, Loader } from 'semantic-ui-react';
import Server from '../lib/Server';
import ModalAlert from '../components/ModalAlert';
import Pane from "./Pane";
export default class Pagination extends React.Component {
......@@ -29,21 +30,32 @@ export default class Pagination extends React.Component {
dir: 0,
start: true,
finish: false,
search: '',
};
this.handleNext = this.handleNext.bind(this);
this.handlePrev = this.handlePrev.bind(this);
this.getItemsData = this.getItemsData.bind(this);
this.handleMovement = this.handleMovement.bind(this);
this.handleSearchChange = this.handleSearchChange.bind(this);
this.handleSearchSubmit = this.handleSearchSubmit.bind(this);
this.refresh = this.refresh.bind(this);
this.content = this.content.bind(this);
this.pageMenu = this.pageMenu.bind(this);
this.getItemsData();
}
getItemsData = () => Server.get(this.state.url, false).then((data) => {
this.setState({ current: this.state.current + this.state.dir });
getItemsData = () => {
const prefix = this.state.dir === 0 ? '?' : '&';
const searchPrefix = this.state.search !== '' ? prefix : '';
const searchValue = this.state.search !== '' ? `search=${this.state.search}` : '';
return Server.get(`${this.state.url}${searchPrefix}${searchValue}`, false).then((data) => {
console.log('GET ITEM DATA');
this.setState({
current: this.state.current + this.state.dir,
});
this.setState(
{ items: data.results,
{
items: data.results,
next: `${this.props.url}?page=${this.state.current + 1}`,
prev: `${this.props.url}?page=${this.state.current - 1}`,
loading: false,
......@@ -56,11 +68,47 @@ export default class Pagination extends React.Component {
if (data.next) {
last = false;
}
this.setState({ first, last });
this.setState({first, last});
}, error => error.then((r) => {
this.modalAlert.open(this.props.error, r.detail);
this.setState({ loading: false });
this.setState({loading: false});
}));
};
handleSearchChange(e) {
this.setState({ search: e.target.value });
if (e.target.value === '') {
this.setState({
items: [],
current: 1,
next: '',
prev: '',
url: this.props.url,
loading: true,
dir: 0,
start: true,
finish: false,
}, function() {
this.getItemsData();
});
}
}
handleSearchSubmit() {
this.setState({
items: [],
current: 1,
next: '',
prev: '',
url: this.props.url,
loading: true,
dir: 0,
start: true,
finish: false,
}, function() {
this.getItemsData();
});
}
refresh() {
this.forceUpdate();
......@@ -112,6 +160,10 @@ export default class Pagination extends React.Component {
render = () => (
<div>
<Loader active={this.state.loading} />
<div className="search-container">
<input type="text" placeholder="Cari Lowongan" onChange={this.handleSearchChange} className="search-form"/>
<button type="submit" onClick={this.handleSearchSubmit} className="search-button">Cari</button>
</div>
<ModalAlert ref={(modal) => { this.modalAlert = modal; }} />
{!this.state.loading && this.content()}
{!this.state.loading && this.pageMenu()}
......
# -*- coding: utf-8 -*-
# Generated by Django 1.10.5 on 2019-10-06 23:48
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('core', '0017_vacancy_amount'),
('core', '0019_merge_20191006_0852'),
('core', '0014_auto_20191004_1340'),
]
operations = [
]
# -*- coding: utf-8 -*-
# Generated by Django 1.10.5 on 2019-10-06 23:48
from __future__ import unicode_literals
import django.core.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0020_merge_20191007_0648'),
]
operations = [
migrations.AlterField(
model_name='company',
name='website',
field=models.CharField(default=b'Belum ada link website', max_length=100),
),
migrations.AlterField(
model_name='student',
name='phone_number',
field=models.CharField(blank=True, db_index=True, max_length=12, null=True, validators=[django.core.validators.RegexValidator(b'^0\\d{1,11}$')]),
),
]
# -*- coding: utf-8 -*-
# Generated by Django 1.10.5 on 2019-10-07 11:10
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('core', '0021_auto_20191007_0648'),
('core', '0024_auto_20191007_1533'),
]
operations = [
]
# -*- coding: utf-8 -*-
# Generated by Django 1.10.5 on 2019-10-07 22:25
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('core', '0025_merge_20191007_1810'),
('core', '0025_merge_20191007_2124'),
('core', '0025_merge_20191008_0048'),
]
operations = [
]
# -*- coding: utf-8 -*-
# Generated by Django 1.10.5 on 2019-10-07 23:52
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('core', '0026_merge_20191008_0525'),
('core', '0026_merge_20191008_0256'),
]
operations = [
]
......@@ -43,6 +43,37 @@ class ApplicationTests(APITestCase):
self.assertEqual(response.status_code, status.HTTP_200_OK)
@requests_mock.Mocker()
def test_application_search(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)
m.post('https://api.cs.ui.ac.id/authentication/ldap/v2/', json={
"username": "dummy.mahasiswa",
"nama": "Dummy Mahasiswa",
"state": 1,
"kode_org": "01.00.12.01:mahasiswa",
"kodeidentitas": "1234567890",
"nama_role": "mahasiswa"
}, status_code=200)
m.get('https://api.cs.ui.ac.id/siakngcs/mahasiswa/1234567890?client_id=X3zNkFmepkdA47ASNMDZRX3Z9gqSU1Lwywu5WepG', json={
"kota_lahir": "kota_kota",
"tgl_lahir": "2017-12-31",
"program": [{
"nm_org": "Ilmu Informasi",
"angkatan": "2017"
}]
}, status_code=200)
url = '/api/login/'
response = self.client.post(url, {'username': 'dummy.mahasiswa', 'password': 'lalala', 'login-type': 'sso-ui'},
format='json')
student_id = response.data.get('student').get('id')
url = '/api/students/' + str(student_id) + '/applied-vacancies/?search=engineer'
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
@requests_mock.Mocker()
def test_application_create_and_delete(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)
......@@ -152,6 +183,42 @@ class BookmarkApplicationTests(APITestCase):
self.assertEqual(response.status_code, status.HTTP_200_OK)
@requests_mock.Mocker()
def test_search_bookmarked_application(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)
m.post('https://api.cs.ui.ac.id/authentication/ldap/v2/', json={
"username": "dummy.mahasiswa",
"nama": "Dummy Mahasiswa",
"state": 1,
"kode_org": "01.00.12.01:mahasiswa",
"kodeidentitas": "1234567890",
"nama_role": "mahasiswa"
}, status_code=200)
m.get(
'https://api.cs.ui.ac.id/siakngcs/mahasiswa/1234567890?client_id=X3zNkFmepkdA47ASNMDZRX3Z9gqSU1Lwywu5WepG',
json={
"kota_lahir": "kota_kota",
"tgl_lahir": "2017-12-31",
"program": [{
"nm_org": "Ilmu Informasi",
"angkatan": "2017"
}]
}, status_code=200)
url = '/api/login/'
response = self.client.post(url,
{'username': 'dummy.mahasiswa', 'password': 'lalala', 'login-type': 'sso-ui'},
format='json')
student_id = response.data.get('student').get('id')
url = '/api/students/' + str(student_id) + '/bookmarked-vacancies/?search=engineer'
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
@requests_mock.Mocker()
def test_application_create_and_delete(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)
......@@ -202,6 +269,44 @@ class VacancyTest(APITestCase):
response = self.client.get(url, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
@requests_mock.Mocker()
def test_search_vacancy(self, m):
superuser = User.objects.create_user('dummy.company', 'dummy.company@company.com', 'lalala123')
company = Company.objects.create(user=superuser, description="This is a test company")
Vacancy.objects.create(company=company, open_time=datetime.now(), close_time=datetime.now(), name="Software Engineer")
Vacancy.objects.create(company=company, open_time=datetime.now(), close_time=datetime.now(), name="Data Engineer")
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)
m.post('https://api.cs.ui.ac.id/authentication/ldap/v2/', json={
"username": "dummy.mahasiswa",
"nama": "Dummy Mahasiswa",
"state": 1,
"kode_org": "01.00.12.01:mahasiswa",
"kodeidentitas": "1234567890",
"nama_role": "mahasiswa"
}, status_code=200)
m.get(
'https://api.cs.ui.ac.id/siakngcs/mahasiswa/1234567890?client_id=X3zNkFmepkdA47ASNMDZRX3Z9gqSU1Lwywu5WepG',
json={
"kota_lahir": "kota_kota",
"tgl_lahir": "2017-12-31",
"program": [{
"nm_org": "Ilmu Informasi",
"angkatan": "2017"
}]
}, status_code=200)
url = '/api/login/'
self.client.post(url, {'username': 'dummy.mahasiswa', 'password': 'lalala', 'login-type': 'sso-ui'}, format='json')
url = '/api/vacancies/?search=software'
response = self.client.get(url, format='json')
self.assertEqual(1, Company.objects.all().count())
self.assertEqual(2, Vacancy.objects.all().count())
self.assertEqual(response.status_code, status.HTTP_200_OK)
def test_unverified_vacancy_list(self):
superuser = User.objects.create_superuser('dummy.company', 'dummy.company@company.com', 'lalala123')
self.client.force_authenticate(user=superuser)
......
import requests
from django.utils import timezone
from django.conf import settings
from django.db.models import Q
from rest_framework import viewsets, status
from rest_framework.decorators import detail_route, permission_classes
from rest_framework.exceptions import ValidationError
......@@ -37,8 +38,12 @@ class VacancyViewSet(MultiSerializerViewSetMixin, viewsets.ModelViewSet):
return super(VacancyViewSet, self).get_permissions()
def list(self, request, *args, **kwargs):
vacancies = Vacancy.objects.all()
verified = request.query_params['verified'] if 'verified' in request.query_params else "True"
search = request.query_params['search'] if 'search' in request.query_params else None
if search is not None:
vacancies = Vacancy.objects.filter(Q(name__icontains=search) | Q(company__user__username__icontains=search))
else:
vacancies = Vacancy.objects.all()
companies = [int(x) for x in request.query_params.getlist('company', [])]
if verified.lower() in ("yes", "true", "t", "1"):
vacancies = vacancies.filter(verified=True)
......@@ -57,6 +62,7 @@ class VacancyViewSet(MultiSerializerViewSetMixin, viewsets.ModelViewSet):
page = self.paginate_queryset(vacancies)
if page is not None:
return self.get_paginated_response(VacancySerializer(page, many=True, context={'request': request}).data)
vacancies = Vacancy.objects.all()
return Response(VacancySerializer(vacancies, many=True, context={'request': request}).data)
def name_position_validator(self, names):
......@@ -185,6 +191,10 @@ class StudentApplicationViewSet(viewsets.GenericViewSet):
"""
student = get_object_or_404(Student.objects.all(), pk=student_id)
vacancy_ids = Application.objects.filter(student=student).values('vacancy')
search = request.query_params['search'] if 'search' in request.query_params else None
if search is not None:
vacancies = Vacancy.objects.filter(Q(id__in=vacancy_ids) & (Q(name__icontains=search) | Q(company__user__username__icontains=search)))
else:
vacancies = Vacancy.objects.filter(id__in=vacancy_ids)
page = self.paginate_queryset(vacancies)
if page is not None:
......@@ -355,6 +365,10 @@ class BookmarkedVacancyByStudentViewSet(viewsets.GenericViewSet):
---
"""
student = get_object_or_404(Student.objects.all(), pk=student_id)
search = request.query_params['search'] if 'search' in request.query_params else None
if search is not None:
vacancies = student.bookmarked_vacancies.filter(Q(name__icontains=search) | Q(company__user__username__icontains=search))
else:
vacancies = student.bookmarked_vacancies.all()
page = self.paginate_queryset(vacancies)
if page is not None:
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment