Fakultas Ilmu Komputer UI
Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Fasilkom UI Open Source Software
Kape
Commits
d502a5a4
Commit
d502a5a4
authored
Apr 26, 2017
by
Zamil Majdy
Browse files
[#140656091] [#33] [Green] Add applicant and approve implementations
parent
e51ee2c8
Changes
7
Hide whitespace changes
Inline
Side-by-side
assets/js/ApplicantPage.jsx
View file @
d502a5a4
...
...
@@ -3,9 +3,9 @@ import Tabs from './components/Tabs';
import
Pane
from
'
./components/Pane
'
;
import
Storage
from
'
./lib/Storage
'
;
import
ApplicantList
from
'
./components/ApplicantList
'
;
import
Applicant
from
'
./components/Applicant
'
;
export
default
class
ApplicantPage
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
);
/* istanbul ignore next */
...
...
@@ -13,7 +13,7 @@ export default class ApplicantPage extends React.Component {
email
:
''
,
password
:
''
,
errorFlag
:
false
,
company
:
{
id
:
1
},
company
:
{
id
:
1
},
};
this
.
handleItemClick
=
this
.
handleItemClick
.
bind
(
this
);
}
...
...
@@ -23,18 +23,23 @@ export default class ApplicantPage extends React.Component {
render
()
{
const
company
=
Storage
.
get
(
'
user-data
'
).
company
;
return
(
<
div
className
=
"halamanPendaftar"
>
<
Tabs
selected
=
{
0
}
>
<
Pane
label
=
"Semua Lamaran"
>
<
ApplicantList
key
=
{
1
}
companyId
=
{
company
.
id
}
url
=
{
`/students/
${
company
.
id
}
/bookmarked-vacancies/`
}
/>
<
Pane
label
=
"Lamaran Baru"
>
<
ApplicantList
key
=
{
1
}
companyId
=
{
company
.
id
}
url
=
{
`/companies/
${
company
.
id
}
/applications/?status=
${
Applicant
.
APPLICATION_STATUS
.
NEW
}
`
}
status
=
{
Applicant
.
APPLICATION_STATUS
.
NEW
}
/>
</
Pane
>
<
Pane
label
=
"Lamaran Dibaca"
>
<
ApplicantList
key
=
{
2
}
companyId
=
{
company
.
id
}
url
=
{
`/companies/
${
company
.
id
}
/applications/?status=
${
Applicant
.
APPLICATION_STATUS
.
READ
}
`
}
status
=
{
Applicant
.
APPLICATION_STATUS
.
READ
}
/>
</
Pane
>
<
Pane
label
=
"Lamaran Ditandai"
>
<
ApplicantList
key
=
{
3
}
companyId
=
{
company
.
id
}
url
=
{
`/companies/
${
company
.
id
}
/applications/?status=
${
Applicant
.
APPLICATION_STATUS
.
BOOKMARKED
}
`
}
status
=
{
Applicant
.
APPLICATION_STATUS
.
BOOKMARKED
}
/>
</
Pane
>
<
Pane
label
=
"Bintangi"
>
<
ApplicantList
key
=
{
2
}
status
=
"Bookmarked"
companyId
=
{
company
.
id
}
url
=
{
`/students/
${
company
.
id
}
/applied-vacancies/`
}
/>
<
Pane
label
=
"Lamaran Diterima"
>
<
ApplicantList
key
=
{
4
}
companyId
=
{
company
.
id
}
url
=
{
`/companies/
${
company
.
id
}
/applications/?status=
${
Applicant
.
APPLICATION_STATUS
.
ACCEPTED
}
`
}
status
=
{
Applicant
.
APPLICATION_STATUS
.
ACCEPTED
}
/>
</
Pane
>
<
Pane
label
=
"Lamaran Ditolak"
>
<
ApplicantList
key
=
{
5
}
companyId
=
{
company
.
id
}
url
=
{
`/companies/
${
company
.
id
}
/applications/?status=
${
Applicant
.
APPLICATION_STATUS
.
REJECTED
}
`
}
status
=
{
Applicant
.
APPLICATION_STATUS
.
REJECTED
}
/>
</
Pane
>
</
Tabs
>
</
div
>
);
}
}
assets/js/components/Applicant.jsx
View file @
d502a5a4
import
React
from
'
react
'
;
import
{
Item
,
Rating
}
from
'
semantic-ui-react
'
;
import
ApproveModal
from
'
./ApproveModal
'
;
import
Storage
from
'
../lib/Storage
'
;
import
{
Item
,
Rating
,
Grid
}
from
'
semantic-ui-react
'
;
import
Server
from
'
../lib/Server
'
;
import
CancelModal
from
'
./CancelModal
'
;
import
ModalAlert
from
'
./ModalAlert
'
;
import
ApproveModal
from
'
./ApproveModal
'
;
const
defaultImage
=
'
http://semantic-ui.com/images/wireframe/image.png
'
;
export
default
class
Applicant
extends
React
.
Component
{
static
propTypes
=
{
data
:
React
.
PropTypes
.
object
.
isRequired
,
bookmarked
:
React
.
PropTypes
.
number
,
status
:
React
.
PropTypes
.
string
.
isRequired
,
updateStatus
:
React
.
PropTypes
.
func
.
isRequired
,
};
static
defaultProps
=
{
bookmarked
:
0
,
static
APPLICATION_STATUS
=
{
NEW
:
0
,
READ
:
1
,
BOOKMARKED
:
2
,
REJECTED
:
3
,
ACCEPTED
:
4
,
};
constructor
(
props
)
{
super
(
props
);
/* istanbul ignore next */
this
.
state
=
{
bookmarked
:
this
.
props
.
bookmarked
};
this
.
bookmark
=
this
.
bookmark
.
bind
(
this
);
this
.
generateAction
=
this
.
generateAction
.
bind
(
this
);
}
bookmark
()
{
/* still under construction */
const
companyId
=
Storage
.
get
(
'
user-data
'
).
company
.
id
;
const
data
=
{
application_id
:
this
.
props
.
data
.
id
};
if
(
this
.
state
.
bookmarked
<
1
)
{
Server
.
post
(
`/company/
${
companyId
}
/bookmarked-applications/`
,
data
);
}
else
{
Server
.
delete
(
`/company/
${
companyId
}
/bookmarked-applications/
${
this
.
props
.
data
.
id
}
/`
);
bookmark
=
()
=>
{
let
data
=
{
status
:
Applicant
.
APPLICATION_STATUS
.
BOOKMARKED
};
if
(
this
.
props
.
data
.
status
===
Applicant
.
APPLICATION_STATUS
.
BOOKMARKED
)
{
data
=
{
status
:
Applicant
.
APPLICATION_STATUS
.
READ
};
}
this
.
state
.
bookmarked
=
1
-
this
.
state
.
bookmarked
;
}
generateAction
()
{
const
approveModal
=
(<
ApproveModal
id
=
{
this
.
props
.
data
.
id
}
data
=
{
{
header
:
this
.
props
.
data
.
name
,
description
:
this
.
props
.
data
.
description
}
}
buttonTitle
=
"Detail"
/>);
return
approveModal
;
}
if
(
this
.
props
.
data
.
status
>
2
)
{
this
.
modalAlert
.
open
(
'
Gagal Menandai
'
,
'
Lamaran yang sudah ditolak atau diterima tidak bisa ditandai
'
);
}
else
{
Server
.
patch
(
`/applications/
${
this
.
props
.
data
.
id
}
/`
,
data
).
then
((
status
)
=>
{
this
.
props
.
updateStatus
(
this
.
props
.
data
.
id
,
status
.
status
);
});
}
};
render
()
{
return
(
<
Item
>
<
ModalAlert
ref
=
{
(
modal
)
=>
{
this
.
modalAlert
=
modal
;
}
}
/>
<
Item
.
Image
size
=
"small"
src
=
{
defaultImage
}
/>
<
Item
.
Content
verticalAlign
=
"middle"
>
<
Item
.
Extra
>
<
h3
>
{
this
.
props
.
data
.
name
}
</
h3
>
<
div
className
=
"bookmark"
>
<
Rating
icon
=
"star"
onRate
=
{
this
.
bookmark
}
size
=
"massive"
defaultRating
=
{
this
.
props
.
bookmarked
?
this
.
props
.
bookmarked
:
0
}
maxRating
=
{
1
}
/>
</
div
>
<
h5
>
{
this
.
props
.
data
.
jurusan
}
</
h5
>
<
h4
>
{
this
.
props
.
data
.
application
}
</
h4
>
{
this
.
generateAction
()
}
<
Grid
.
Row
>
<
Grid
.
Column
floated
=
"left"
>
<
h4
>
{
this
.
props
.
data
.
student
.
name
}
</
h4
>
{
this
.
props
.
data
.
vacancy
.
name
}
<
br
/>
{
this
.
props
.
data
.
student
.
major
}
</
Grid
.
Column
>
<
Grid
.
Column
floated
=
"right"
textAlign
=
"center"
>
<
Grid
.
Row
>
<
Rating
icon
=
"star"
size
=
"massive"
defaultRating
=
{
this
.
props
.
data
.
status
===
Applicant
.
APPLICATION_STATUS
.
BOOKMARKED
?
1
:
0
}
onRate
=
{
this
.
bookmark
}
maxRating
=
{
1
}
/>
</
Grid
.
Row
>
<
ApproveModal
updateStatus
=
{
this
.
props
.
updateStatus
}
data
=
{
this
.
props
.
data
}
/>
</
Grid
.
Column
>
</
Grid
.
Row
>
</
Item
.
Extra
>
</
Item
.
Content
>
</
Item
>
...
...
assets/js/components/ApplicantList.jsx
View file @
d502a5a4
import
React
from
'
react
'
;
import
{
Item
}
from
'
semantic-ui-react
'
;
import
{
Item
,
Grid
}
from
'
semantic-ui-react
'
;
import
Applicant
from
'
./Applicant
'
;
import
Server
from
'
../lib/Server
'
;
...
...
@@ -7,41 +7,47 @@ export default class ApplicantList extends React.Component {
static
propTypes
=
{
url
:
React
.
PropTypes
.
string
.
isRequired
,
companyId
:
React
.
PropTypes
.
number
.
isRequired
,
status
:
React
.
PropTypes
.
string
,
status
:
React
.
PropTypes
.
number
.
isRequired
,
};
static
defaultProps
=
{
status
:
'
Unbookmarked
'
,
};
constructor
(
props
)
{
super
(
props
);
/* istanbul ignore next */
/*
this
.
state
=
{
applications
:
[]
};
Server
.
get
(
this
.
props
.
url
,
false
).
then
((
data
)
=>
{
this
.
setState
({
applications
:
data
});
});
*/
this
.
state
=
{
applications
:
[{
id
:
1
,
name
:
"
Farasdak
"
,
description
:
"
huehuehuehue
"
,
bookmarked
:
0
,
jurusan
:
"
Ilmu Komputer
"
,
application
:
"
Software Engineer
"
}],
bookmarkList
:
[]
};
this
.
generateApplicants
=
this
.
generateApplicants
.
bind
(
this
);
this
.
updateStatus
=
this
.
updateStatus
.
bind
(
this
);
}
updateStatus
(
id
,
status
)
{
const
obj
=
[];
this
.
state
.
applications
.
map
((
application
)
=>
{
const
clonedObj
=
{};
Object
.
assign
(
clonedObj
,
application
);
if
(
application
.
id
===
id
)
clonedObj
.
status
=
status
;
return
obj
.
push
(
clonedObj
);
});
this
.
setState
({
applications
:
obj
});
}
generateApplicants
()
{
console
.
log
(
this
.
state
.
applications
)
return
this
.
state
.
applications
.
map
(
application
=>
<
Applicant
key
=
{
application
.
id
}
status
=
{
this
.
props
.
status
}
data
=
{
application
}
/>,
application
.
status
===
this
.
props
.
status
&&
(<
Applicant
key
=
{
application
.
id
}
data
=
{
application
}
updateStatus
=
{
this
.
updateStatus
}
/>),
);
}
render
=
()
=>
(
<
Item
.
Group
relaxed
>
{
this
.
generateApplicants
()
}
</
Item
.
Group
>
<
Grid
container
doubling
>
<
Item
.
Group
relaxed
style
=
{
{
width
:
'
100%
'
}
}
>
{
this
.
generateApplicants
()
}
</
Item
.
Group
>
</
Grid
>
);
}
assets/js/components/ApproveModal.jsx
View file @
d502a5a4
import
React
from
'
react
'
;
import
{
Modal
,
Button
,
Icon
,
TextArea
,
Form
}
from
'
semantic-ui-react
'
;
import
ModalAlert
from
'
./ModalAlert
'
;
import
{
Modal
,
Button
}
from
'
semantic-ui-react
'
;
import
Server
from
'
./../lib/Server
'
;
import
ConfirmationModal
from
'
./../components/ConfirmationModal
'
;
import
Applicant
from
'
./../components/Applicant
'
;
export
default
class
ApproveModal
extends
React
.
Component
{
static
propTypes
=
{
data
:
React
.
PropTypes
.
object
.
isRequired
,
id
:
React
.
PropTypes
.
number
.
isRequired
,
buttonTitle
:
React
.
PropTypes
.
string
.
isRequired
,
updateStatus
:
React
.
PropTypes
.
func
.
isRequired
,
};
constructor
(
props
)
{
...
...
@@ -14,50 +15,73 @@ export default class ApproveModal extends React.Component {
/* istanbul ignore next */
this
.
state
=
{
modalOpen
:
false
,
rejectLoading
:
false
,
acceptLoading
:
false
,
};
this
.
handleOpen
=
this
.
handleOpen
.
bind
(
this
);
this
.
reject
=
this
.
reject
.
bind
(
this
);
this
.
accept
=
this
.
accept
.
bind
(
this
);
}
handleOpen
=
()
=>
this
.
setState
({
modalOpen
:
true
});
handleClose
=
()
=>
this
.
setState
({
modalOpen
:
false
});
handleOpen
()
{
this
.
setState
({
modalOpen
:
true
});
}
rejectApplication
=
()
=>
{
const
data
=
{
status
:
Applicant
.
APPLICATION_STATUS
.
REJECTED
};
this
.
setState
({
rejectLoading
:
true
});
Server
.
patch
(
`/applications/
${
this
.
props
.
data
.
id
}
/`
,
data
).
then
((
status
)
=>
{
this
.
props
.
updateStatus
(
this
.
props
.
data
.
id
,
status
.
status
);
});
};
reject
=
()
=>
{
this
.
modal
.
open
(
'
Tolak Lamaran?
'
,
'
Apakah anda yakin untuk menolak lamaran ini?
'
,
'
trash
'
,
this
.
rejectApplication
,
);
};
handleClose
=
()
=>
this
.
setState
({
modalOpen
:
false
,
});
acceptApplication
=
()
=>
{
const
data
=
{
status
:
Applicant
.
APPLICATION_STATUS
.
ACCEPTED
};
this
.
setState
({
acceptLoading
:
true
});
Server
.
patch
(
`/applications/
${
this
.
props
.
data
.
id
}
/`
,
data
).
then
((
status
)
=>
{
this
.
props
.
updateStatus
(
this
.
props
.
data
.
id
,
status
.
status
);
});
};
accept
=
()
=>
{
this
.
modal
.
open
(
'
Terima Lamaran?
'
,
'
Apakah anda yakin untuk menerima lamaran ini?
'
,
'
checkmark
'
,
this
.
acceptApplication
,
);
};
render
=
()
=>
(
<
Modal
trigger
=
{
<
Button
primary
onClick
=
{
this
.
handleOpen
}
floated
=
"right"
>
{
this
.
props
.
buttonTitle
}
</
Button
>
}
trigger
=
{
<
Button
primary
onClick
=
{
this
.
handleOpen
}
floated
=
"right"
>
Detail
</
Button
>
}
closeIcon
=
"close"
open
=
{
this
.
state
.
modalOpen
}
onClose
=
{
this
.
handleClose
}
>
<
Modal
.
Header
>
{
this
.
props
.
data
.
header
}
</
Modal
.
Header
>
<
ConfirmationModal
ref
=
{
(
modal
)
=>
{
this
.
modal
=
modal
;
}
}
/>
<
Modal
.
Header
>
Data Lamaran
</
Modal
.
Header
>
<
Modal
.
Content
>
<
div
className
=
"coverLetter"
>
<
div
className
=
"linkCV"
>
<
a
>
Applicant's CV
</
a
>
</
div
>
<
h4
>
Cover Letter
</
h4
>
<
h5
>
{
this
.
props
.
data
.
description
}
</
h5
>
</
div
>
<
h4
>
Cover Letter
</
h4
>
{
this
.
props
.
data
.
cover_letter
}
<
div
style
=
{
{
float
:
'
right
'
}
}
>
<
a
href
=
{
this
.
props
.
data
.
resume
}
>
CV Pelamar
</
a
>
</
div
>
</
Modal
.
Content
>
<
Modal
.
Actions
>
<
ModalAlert
id
=
{
this
.
props
.
id
}
onChangeValue
=
{
this
.
handleClose
}
status
=
"Terima"
/
>
<
Button
.
Group
>
<
Button
disabled
=
{
this
.
props
.
data
.
status
===
Applicant
.
APPLICATION_STATUS
.
REJECTED
}
loading
=
{
this
.
state
.
rejectLoading
}
color
=
"red"
onClick
=
{
this
.
reject
}
>
Tolak Lamaran
</
Button
>
<
Button
.
Or
/>
<
Button
disabled
=
{
this
.
props
.
data
.
status
===
Applicant
.
APPLICATION_STATUS
.
ACCEPTED
}
loading
=
{
this
.
state
.
acceptLoading
}
color
=
"green"
onClick
=
{
this
.
accept
}
>
Terima Lamaran
</
Button
>
</
Button
.
Group
>
</
Modal
.
Actions
>
</
Modal
>
)
...
...
assets/js/components/Vacancy.jsx
View file @
d502a5a4
import
React
from
'
react
'
;
import
{
Item
,
Rating
,
Button
}
from
'
semantic-ui-react
'
;
import
{
Item
,
Rating
,
Button
,
Grid
}
from
'
semantic-ui-react
'
;
import
ApplyModal
from
'
./ApplyModal
'
;
import
Server
from
'
../lib/Server
'
;
import
ConfirmationModal
from
'
./ConfirmationModal
'
;
...
...
@@ -92,16 +92,21 @@ export default class Vacancy extends React.Component {
<
Item
.
Image
size
=
"small"
src
=
{
this
.
props
.
data
.
company
.
logo
?
this
.
props
.
data
.
company
.
logo
:
defaultImage
}
/>
<
Item
.
Content
verticalAlign
=
"middle"
>
<
Item
.
Extra
>
<
h3
>
{
this
.
props
.
data
.
name
}
</
h3
>
<
div
className
=
"bookmark"
>
<
Rating
icon
=
"star"
onRate
=
{
this
.
bookmark
}
size
=
"massive"
defaultRating
=
{
this
.
props
.
bookmarked
}
maxRating
=
{
1
}
/>
</
div
>
<
h4
>
{
this
.
props
.
data
.
company
.
name
}
</
h4
>
<
h5
>
{
this
.
props
.
data
.
company
.
address
}
</
h5
>
{
this
.
generateAction
()
}
<
Grid
.
Row
>
<
Grid
.
Column
floated
=
"left"
>
<
h4
>
{
this
.
props
.
data
.
name
}
</
h4
>
{
this
.
props
.
data
.
company
.
name
}
<
br
/>
{
this
.
props
.
data
.
company
.
address
}
</
Grid
.
Column
>
<
Grid
.
Column
floated
=
"right"
>
<
Grid
.
Row
textAlign
=
"center"
>
<
Rating
icon
=
"star"
onRate
=
{
this
.
bookmark
}
size
=
"massive"
defaultRating
=
{
this
.
props
.
bookmarked
}
maxRating
=
{
1
}
/>
</
Grid
.
Row
>
<
Grid
.
Row
>
{
this
.
generateAction
()
}
</
Grid
.
Row
>
</
Grid
.
Column
>
</
Grid
.
Row
>
</
Item
.
Extra
>
</
Item
.
Content
>
</
Item
>
...
...
assets/js/components/VacancyList.jsx
View file @
d502a5a4
...
...
@@ -105,7 +105,7 @@ export default class VacancyList extends React.Component {
}
render
=
()
=>
(
<
Segment
>
<
div
>
<
ModalAlert
ref
=
{
(
modal
)
=>
{
this
.
modalAlert
=
modal
;
}
}
/>
<
Grid
container
columns
=
"eleven"
doubling
>
{
this
.
companyHeader
()
}
...
...
@@ -113,6 +113,6 @@ export default class VacancyList extends React.Component {
{
this
.
generateVacancies
()
}
</
Item
.
Group
>
</
Grid
>
</
Segment
>
</
div
>
);
}
core/views/vacancies.py
View file @
d502a5a4
...
...
@@ -92,8 +92,10 @@ class CompanyApplicationViewSet(viewsets.GenericViewSet):
---
"""
company
=
get_object_or_404
(
Company
.
objects
.
all
(),
pk
=
company_id
)
vacancies
=
Vacancy
.
objects
.
filter
(
company
=
company
)
applications
=
Application
.
objects
.
filter
(
vacancy__in
=
vacancies
)
vacancies
=
Vacancy
.
objects
.
filter
(
company
=
company
)
applications
=
Application
.
objects
.
filter
(
vacancy__in
=
vacancies
)
if
'status'
in
request
.
query_params
:
applications
=
applications
.
filter
(
status
=
request
.
query_params
[
'status'
])
return
Response
(
ApplicationSerializer
(
applications
,
many
=
True
,
context
=
{
'request'
:
request
}).
data
)
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment