[UPDT] RECRUITMENT: Candidate profile update method

This commit is contained in:
Horilla
2023-10-09 16:17:34 +05:30
parent d285768b03
commit aadcdcdbd3
3 changed files with 218 additions and 115 deletions

View File

@@ -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 %}

View File

@@ -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,

View File

@@ -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):