[UPDT] RECRUITMENT: Candidate profile update method
This commit is contained in:
@@ -1,14 +1,25 @@
|
||||
{% extends 'index.html' %}
|
||||
{% block content %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% extends 'index.html' %} {% block content %} {% load static %} {% load i18n %}
|
||||
{% comment %} {% include 'candidate/candidate_nav.html' %} {% endcomment %}
|
||||
|
||||
{{form.load}}
|
||||
<div class="oh-wrapper mt-5" id='section' data-select2-id="select2-data-40-yu7x">
|
||||
<form data-select2-id="select2-data-47-5jxy" method="post" enctype="multipart/form-data">
|
||||
<div class="oh-general__tab-target oh-profile-section mb-4" id="personal" data-select2-id="select2-data-personal">
|
||||
<div class="oh-profile-section__card" data-select2-id="select2-data-48-0df8">
|
||||
<div
|
||||
class="oh-wrapper mt-5"
|
||||
id="section"
|
||||
data-select2-id="select2-data-40-yu7x"
|
||||
>
|
||||
<form
|
||||
data-select2-id="select2-data-47-5jxy"
|
||||
method="post"
|
||||
enctype="multipart/form-data"
|
||||
>
|
||||
<div
|
||||
class="oh-general__tab-target oh-profile-section mb-4"
|
||||
id="personal"
|
||||
data-select2-id="select2-data-personal"
|
||||
>
|
||||
<div
|
||||
class="oh-profile-section__card"
|
||||
data-select2-id="select2-data-48-0df8"
|
||||
>
|
||||
<div id="personalMessage">
|
||||
{% if messages %}
|
||||
<div class="oh-alert-container">
|
||||
@@ -22,154 +33,190 @@
|
||||
</div>
|
||||
{% csrf_token %}
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-12 col-md-12 col-lg-6 d-flex align-items-center">
|
||||
<div class="oh-profile-section__edit-photo me-4 mb-3" data-toggle="oh-modal-toggle"
|
||||
data-target="#uploadPhotoModal">
|
||||
{% if form.instance == None or form.instance.profile == None %}
|
||||
<img src="https://ui-avatars.com/api/?name=n+p&background=random"
|
||||
class="oh-profile-section__avatar preview" />
|
||||
<div
|
||||
class="col-12 col-sm-12 col-md-12 col-lg-6 d-flex align-items-center"
|
||||
>
|
||||
<div
|
||||
class="oh-profile-section__edit-photo me-4 mb-3"
|
||||
data-toggle="oh-modal-toggle"
|
||||
data-target="#uploadPhotoModal"
|
||||
>
|
||||
{% if form.instance.profile %}
|
||||
<img
|
||||
src="/media/{{form.instance.profile}}"
|
||||
class="oh-profile-section__modal-image preview"
|
||||
alt="Username"
|
||||
/>
|
||||
{% else %}
|
||||
<img src="/media/{{form.instance.profile}}"
|
||||
class="oh-profile-section__avatar preview" />
|
||||
{% endif %}
|
||||
<img
|
||||
src="https://ui-avatars.com/api/?name={{form.name.value}}"
|
||||
class="oh-profile-section__modal-image preview"
|
||||
alt="Username"
|
||||
/>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<input type="file" hidden name="profile" id="hidden_profile">
|
||||
<input type="file" hidden name="profile" id="hidden_profile" />
|
||||
{{form.profile.errors}}
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-12 col-md-12 col-lg-12">
|
||||
<label class="oh-label" for="firstname">{% trans "Candidate Name" %} *</label>
|
||||
{{form.name}}
|
||||
{{form.name.errors}}
|
||||
<label class="oh-label" for="firstname"
|
||||
>{% trans "Candidate Name" %} *</label
|
||||
>
|
||||
{{form.name}} {{form.name.errors}}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-12 col-md-12 col-lg-6">
|
||||
<label class="oh-label" for="email">{% trans "Email" %} *</label>
|
||||
{{form.email}}
|
||||
{{form.email.errors}}
|
||||
{{form.email}} {{form.email.errors}}
|
||||
</div>
|
||||
<div class="col-12 col-sm-12 col-md-12 col-lg-6">
|
||||
<label class="oh-label" for="phone">{% trans "Phone" %}</label>
|
||||
{{form.mobile}}
|
||||
{{form.mobile.errors}}
|
||||
{{form.mobile}} {{form.mobile.errors}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-12 col-md-12 col-lg-6">
|
||||
<label class="oh-label" for="recruitment">{% trans "Recruitment" %}</label>
|
||||
<div id="select2-container">
|
||||
{{form.recruitment_id}}
|
||||
</div>
|
||||
<label class="oh-label" for="recruitment"
|
||||
>{% trans "Recruitment" %}</label
|
||||
>
|
||||
<div id="select2-container">{{form.recruitment_id}}</div>
|
||||
{{form.recruitment_id.errors}}
|
||||
</div>
|
||||
<div class="col-12 col-sm-12 col-md-12 col-lg-6">
|
||||
<label class="oh-label" for="recruitment">{% trans "Job Position" %}</label>
|
||||
<div id="select2-container">
|
||||
{{form.job_position_id}}
|
||||
</div>
|
||||
<label class="oh-label" for="recruitment"
|
||||
>{% trans "Job Position" %}</label
|
||||
>
|
||||
<div id="select2-container">{{form.job_position_id}}</div>
|
||||
{{form.job_position_id.errors}}
|
||||
</div>
|
||||
{% comment %} <div class="col-12 col-sm-12 col-md-12 col-lg-6">
|
||||
{% comment %}
|
||||
<div class="col-12 col-sm-12 col-md-12 col-lg-6">
|
||||
<label class="oh-label" for="stage">{% trans "Stage" %}</label>
|
||||
{{form.stage_id}}
|
||||
{{form.stage_id.errors}}
|
||||
</div> {% endcomment %}
|
||||
{{form.stage_id}} {{form.stage_id.errors}}
|
||||
</div>
|
||||
{% endcomment %}
|
||||
</div>
|
||||
<div class="row" data-select2-id="select2-data-46-nz80">
|
||||
<div class="col-12 col-sm-12 col-md-12 col-lg-6" style="position: relative;">
|
||||
<label class="oh-label" for="dob">{% trans "Date of Birth" %}</label>
|
||||
{{form.dob}}
|
||||
{{form.dob.errors}}
|
||||
<div
|
||||
class="col-12 col-sm-12 col-md-12 col-lg-6"
|
||||
style="position: relative"
|
||||
>
|
||||
<label class="oh-label" for="dob"
|
||||
>{% trans "Date of Birth" %}</label
|
||||
>
|
||||
{{form.dob}} {{form.dob.errors}}
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-sm-12 col-md-12 col-lg-6" data-select2-id="select2-data-45-37n6">
|
||||
<div
|
||||
class="col-12 col-sm-12 col-md-12 col-lg-6"
|
||||
data-select2-id="select2-data-45-37n6"
|
||||
>
|
||||
<label class="oh-label" for="gender">{% trans "Gender" %} *</label>
|
||||
{{form.gender}}
|
||||
{{form.gender.errors}}
|
||||
{{form.gender}} {{form.gender.errors}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-12 col-md-12 col-lg-12">
|
||||
<label class="oh-label" for="address">{% trans "Address" %}</label>
|
||||
{{form.address}}
|
||||
{{form.address.errors}}
|
||||
{{form.address}} {{form.address.errors}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-12 col-md-12 col-lg-6">
|
||||
<label class="oh-label" for="country">{% trans "Country" %}</label>
|
||||
<select name="country" id="id_country" class="oh-select oh-select-2">
|
||||
<option value="{{form.instance.country}}" selected>{{form.instance.country}}</option>
|
||||
<select
|
||||
name="country"
|
||||
id="id_country"
|
||||
class="oh-select oh-select-2"
|
||||
>
|
||||
<option value="{{form.instance.country}}" selected>
|
||||
{{form.instance.country}}
|
||||
</option>
|
||||
</select>
|
||||
{{form.country.errors}}
|
||||
<span class="dropdown-wrapper" aria-hidden="true"></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="col-12 col-sm-12 col-md-12 col-lg-6">
|
||||
<label class="oh-label d-block" for="state">{% trans "State" %}</label>
|
||||
<label class="oh-label d-block" for="state"
|
||||
>{% trans "State" %}</label
|
||||
>
|
||||
{{form.state.errors}}
|
||||
<select name="state" id="id_state" class="oh-select oh-select-2">
|
||||
<option value="{{form.instance.state}}" selected>{{form.instance.state}}</option>
|
||||
<option value="{{form.instance.state}}" selected>
|
||||
{{form.instance.state}}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-12 col-md-12 col-lg-6">
|
||||
<label class="oh-label d-block" for="state">{% trans "Zip Code" %}</label>
|
||||
{{form.zip}}
|
||||
{{form.zip.errors}}
|
||||
<label class="oh-label d-block" for="state"
|
||||
>{% trans "Zip Code" %}</label
|
||||
>
|
||||
{{form.zip}} {{form.zip.errors}}
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-sm-12 col-md-12 col-lg-6">
|
||||
<label class="oh-label d-block" for="state">{% trans "Resume" %} *</label>
|
||||
{{form.resume}}
|
||||
{{form.resume.errors}}
|
||||
<label class="oh-label d-block" for="state"
|
||||
>{% trans "Resume" %} *</label
|
||||
>
|
||||
{{form.resume}} {{form.resume.errors}}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="row">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-12 col-md-12 col-lg-6">
|
||||
<label class="oh-label d-block" for="experience">{% trans "Canceled" %}?</label>
|
||||
<label class="oh-label d-block" for="experience"
|
||||
>{% trans "Canceled" %}?</label
|
||||
>
|
||||
<div class="oh-switch">
|
||||
{{form.canceled}}
|
||||
{{form.canceled.errors}}
|
||||
{{form.canceled}} {{form.canceled.errors}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-sm-12 col-md-12 col-lg-6">
|
||||
<label class="oh-label me-2" for="isActive">{% trans "Is Active" %}?</label>
|
||||
<label class="oh-label me-2" for="isActive"
|
||||
>{% trans "Is Active" %}?</label
|
||||
>
|
||||
<div class="oh-switch">
|
||||
{{form.is_active}}
|
||||
{{form.is_active.errors}}
|
||||
{{form.is_active}} {{form.is_active.errors}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-12 col-md-12 col-lg-6">
|
||||
<input type="file" name="profile" hidden id="hidden_profile">
|
||||
<input type="file" name="profile" hidden id="hidden_profile" />
|
||||
</div>
|
||||
<hr class="mt-5 mb-3 d-flex flex-row-reverse" />
|
||||
</div>
|
||||
|
||||
<hr class="mt-5 mb-3">
|
||||
<div class="w-100 d-flex align-items-center justify-content-end">
|
||||
<button type="submit" class="oh-btn oh-btn--secondary oh-btn--w-100-resp">
|
||||
<button
|
||||
type="submit"
|
||||
class="oh-btn oh-btn--secondary oh-btn--w-100-resp"
|
||||
>
|
||||
{% trans "Save Changes" %}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="oh-modal" id="uploadPhotoModal" role="dialog" aria-labelledby="uploadPhotoModal" aria-hidden="true">
|
||||
<div
|
||||
class="oh-modal"
|
||||
id="uploadPhotoModal"
|
||||
role="dialog"
|
||||
aria-labelledby="uploadPhotoModal"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div class="oh-modal__dialog">
|
||||
<div class="oh-modal__dialog-header">
|
||||
<span class="oh-modal__dialog-title" id="uploadPhotoModalLabel">{% trans "Upload Photo" %}</span>
|
||||
<span class="oh-modal__dialog-title" id="uploadPhotoModalLabel"
|
||||
>{% trans "Upload Photo" %}</span
|
||||
>
|
||||
<a href="#" class="oh-modal__close" aria-label="Close">
|
||||
<ion-icon name="close-outline"></ion-icon>
|
||||
</a>
|
||||
@@ -178,46 +225,70 @@
|
||||
<div class="oh-profile-section__image-container">
|
||||
{% csrf_token %}
|
||||
<div class="oh-profile-section__modal-avatar">
|
||||
|
||||
{% if form.instance.profile %}
|
||||
<img
|
||||
src="https://ui-avatars.com/api/?name=n+p&background=random"
|
||||
class="oh-profile-section__modal-image preview" alt="Username" />
|
||||
|
||||
src="/media/{{form.instance.profile}}"
|
||||
class="oh-profile-section__modal-image preview"
|
||||
alt="Username"
|
||||
/>
|
||||
{% else %}
|
||||
<img
|
||||
src="https://ui-avatars.com/api/?name={{form.name.value}}"
|
||||
class="oh-profile-section__modal-image preview"
|
||||
alt="Username"
|
||||
/>
|
||||
{% endif %}
|
||||
</div>
|
||||
<input type="file" accept="image/*" class="oh-input w-100" placeholder="Profile" id="choose_profile">
|
||||
<div class="d-flex justify-content-between w-100 align-items-center mt-4">
|
||||
|
||||
<input
|
||||
type="file"
|
||||
accept="image/*"
|
||||
class="oh-input oh-input--file oh-input--file-sm mt-4"
|
||||
placeholder="Profile"
|
||||
id="choose_profile"
|
||||
/>
|
||||
<div class="d-flex justify-content-center">
|
||||
<a
|
||||
class="oh-btn oh-btn--light-danger mr-1"
|
||||
href="{% url 'delete-profile-image' form.instance.id %}"
|
||||
>
|
||||
<ion-icon class="me-1" name="trash-outline"></ion-icon>{% trans "Delete Image" %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
{% include 'country.js' %}
|
||||
</script>
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
$("#choose_profile").change(function (e) {
|
||||
var modal_profile = $(this)[0];
|
||||
var hidden_profile = $("#hidden_profile")[0];
|
||||
|
||||
console.log(modal_profile.files);
|
||||
hidden_profile.files = modal_profile.files;
|
||||
console.log(hidden_profile.files);
|
||||
|
||||
const file = this.files[0];
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.addEventListener("load", function () {
|
||||
const imageUrl = reader.result;
|
||||
$(".preview").attr("src", imageUrl);
|
||||
setTimeout(function () {
|
||||
$("#uploadPhotoModal").removeClass("oh-modal--show");
|
||||
}, 2000);
|
||||
});
|
||||
|
||||
reader.readAsDataURL(file);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
<script src="{% static '/recruitment/stageScript.js' %}"></script>
|
||||
{% endblock content %}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
{% include 'country.js' %}
|
||||
</script>
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
$('#choose_profile').change(function (e) {
|
||||
var modal_profile = $(this)[0];
|
||||
var hidden_profile = $('#hidden_profile')[0];
|
||||
|
||||
console.log(modal_profile.files);
|
||||
hidden_profile.files = modal_profile.files;
|
||||
console.log(hidden_profile.files);
|
||||
|
||||
const file = this.files[0];
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.addEventListener("load", function () {
|
||||
const imageUrl = reader.result;
|
||||
$(".preview").attr("src", imageUrl);
|
||||
});
|
||||
|
||||
reader.readAsDataURL(file);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
<script src="{% static '/recruitment/stageScript.js' %}"></script>
|
||||
{% endblock content %}
|
||||
@@ -97,7 +97,11 @@ urlpatterns = [
|
||||
path("create-note/<int:cand_id>/", views.create_note, name="create-note"),
|
||||
path("create-note", views.create_note, name="create-note-post"),
|
||||
path("note-update/<int:note_id>/", views.note_update, name="note-update"),
|
||||
path("note-update-individual/<int:note_id>/", views.note_update_individual, name="note-update-individual"),
|
||||
path(
|
||||
"note-update-individual/<int:note_id>/",
|
||||
views.note_update_individual,
|
||||
name="note-update-individual",
|
||||
),
|
||||
path(
|
||||
"note-delete/<int:note_id>/",
|
||||
recruitment.views.actions.note_delete,
|
||||
@@ -132,6 +136,11 @@ urlpatterns = [
|
||||
views.candidate_update,
|
||||
name="rec-candidate-update",
|
||||
),
|
||||
path(
|
||||
"delete-profile-image/<int:obj_id>/",
|
||||
views.delete_profile_image,
|
||||
name="delete-profile-image",
|
||||
),
|
||||
path(
|
||||
"candidate-delete/<int:cand_id>/",
|
||||
recruitment.views.actions.candidate_delete,
|
||||
|
||||
@@ -11,9 +11,10 @@ This module is part of the recruitment project and is intended to
|
||||
provide the main entry points for interacting with the application's functionality.
|
||||
"""
|
||||
|
||||
|
||||
import contextlib
|
||||
import os
|
||||
import json
|
||||
import contextlib
|
||||
from django.conf import settings
|
||||
from django.http import JsonResponse, HttpResponse, HttpResponseRedirect
|
||||
from django.shortcuts import render, redirect
|
||||
from django.core import serializers
|
||||
@@ -144,7 +145,7 @@ def recruitment_view(request):
|
||||
if not request.GET:
|
||||
request.GET.copy().update({"is_active": "on"})
|
||||
form = RecruitmentCreationForm()
|
||||
queryset=Recruitment.objects.all()
|
||||
queryset = Recruitment.objects.all()
|
||||
if queryset.exists():
|
||||
template = "recruitment/recruitment_view.html"
|
||||
else:
|
||||
@@ -595,6 +596,7 @@ def note_update(request, note_id):
|
||||
request, "pipeline/pipeline_components/update_note.html", {"form": form}
|
||||
)
|
||||
|
||||
|
||||
@login_required
|
||||
@permission_required(perm="recruitment.change_stagenote")
|
||||
def note_update_individual(request, note_id):
|
||||
@@ -611,7 +613,9 @@ def note_update_individual(request, note_id):
|
||||
form.save()
|
||||
messages.success(request, _("Note updated successfully..."))
|
||||
response = render(
|
||||
request, "pipeline/pipeline_components/update_note_individual.html", {"form": form}
|
||||
request,
|
||||
"pipeline/pipeline_components/update_note_individual.html",
|
||||
{"form": form},
|
||||
)
|
||||
return HttpResponse(
|
||||
response.content.decode("utf-8") + "<script>location.reload();</script>"
|
||||
@@ -813,7 +817,7 @@ def candidate_view(request):
|
||||
previous_data = request.GET.urlencode()
|
||||
candidates = Candidate.objects.filter(is_active=True)
|
||||
candidate_all = Candidate.objects.all()
|
||||
filter_obj = CandidateFilter(request.GET,queryset=candidates)
|
||||
filter_obj = CandidateFilter(request.GET, queryset=candidates)
|
||||
if candidate_all.exists():
|
||||
template = "candidate/candidate_view.html"
|
||||
else:
|
||||
@@ -922,6 +926,25 @@ def candidate_update(request, cand_id):
|
||||
return render(request, "candidate/candidate_create_form.html", {"form": form})
|
||||
|
||||
|
||||
@login_required
|
||||
@manager_can_enter(perm="recruitment.change_candidate")
|
||||
def delete_profile_image(request, obj_id):
|
||||
candidate_obj = Candidate.objects.get(id=obj_id)
|
||||
try:
|
||||
if candidate_obj.profile:
|
||||
file_path = candidate_obj.profile.path
|
||||
absolute_path = os.path.join(settings.MEDIA_ROOT, file_path)
|
||||
os.remove(absolute_path)
|
||||
candidate_obj.profile = None
|
||||
candidate_obj.save()
|
||||
messages.success(request, _("Profile image removed."))
|
||||
except Exception as e:
|
||||
pass
|
||||
return redirect('rec-candidate-update', cand_id=obj_id)
|
||||
|
||||
|
||||
|
||||
|
||||
@login_required
|
||||
@permission_required(perm="recruitment.view_history")
|
||||
def candidate_history(request, cand_id):
|
||||
|
||||
Reference in New Issue
Block a user