image upload
This commit is contained in:
parent
67a951c45a
commit
7b02120508
BIN
db.sqlite3
BIN
db.sqlite3
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -5,7 +5,7 @@ from django.utils import timezone
|
||||
from .models import (
|
||||
JobPosting, Candidate, TrainingMaterial, ZoomMeeting,
|
||||
FormTemplate, FormStage, FormField, FormSubmission, FieldResponse,
|
||||
SharedFormTemplate, Source, HiringAgency, IntegrationLog,InterviewSchedule,Profile
|
||||
SharedFormTemplate, Source, HiringAgency, IntegrationLog,InterviewSchedule,Profile,JobPostingImage
|
||||
)
|
||||
|
||||
class FormFieldInline(admin.TabularInline):
|
||||
@ -263,3 +263,6 @@ admin.site.register(FieldResponse)
|
||||
admin.site.register(InterviewSchedule)
|
||||
admin.site.register(Profile)
|
||||
# admin.site.register(HiringAgency)
|
||||
|
||||
|
||||
admin.site.register(JobPostingImage)
|
||||
@ -5,7 +5,10 @@ from django.forms.formsets import formset_factory
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from crispy_forms.helper import FormHelper
|
||||
from crispy_forms.layout import Layout, Submit, Row, Column, Field, Div
|
||||
from .models import ZoomMeeting, Candidate,TrainingMaterial,JobPosting,FormTemplate,InterviewSchedule,BreakTime
|
||||
from .models import (
|
||||
ZoomMeeting, Candidate,TrainingMaterial,JobPosting,
|
||||
FormTemplate,InterviewSchedule,BreakTime,JobPostingImage
|
||||
)
|
||||
# from django_summernote.widgets import SummernoteWidget
|
||||
from django_ckeditor_5.widgets import CKEditor5Widget
|
||||
|
||||
@ -192,8 +195,8 @@ class JobPostingForm(forms.ModelForm):
|
||||
fields = [
|
||||
'title', 'department', 'job_type', 'workplace_type',
|
||||
'location_city', 'location_state', 'location_country',
|
||||
'description', 'qualifications', 'salary_range', 'benefits',
|
||||
'application_url', 'application_deadline', 'application_instructions',
|
||||
'description', 'qualifications', 'salary_range', 'benefits'
|
||||
,'application_deadline', 'application_instructions',
|
||||
'position_number', 'reporting_to', 'start_date', 'status',
|
||||
'created_by','open_positions','hash_tags'
|
||||
]
|
||||
@ -239,11 +242,11 @@ class JobPostingForm(forms.ModelForm):
|
||||
|
||||
|
||||
# Application Information
|
||||
'application_url': forms.URLInput(attrs={
|
||||
'class': 'form-control',
|
||||
'placeholder': 'https://university.edu/careers/job123',
|
||||
'required': True
|
||||
}),
|
||||
# 'application_url': forms.URLInput(attrs={
|
||||
# 'class': 'form-control',
|
||||
# 'placeholder': 'https://university.edu/careers/job123',
|
||||
# 'required': True
|
||||
# }),
|
||||
'application_deadline': forms.DateInput(attrs={
|
||||
'class': 'form-control',
|
||||
'type': 'date'
|
||||
@ -356,6 +359,10 @@ class JobPostingForm(forms.ModelForm):
|
||||
|
||||
return cleaned_data
|
||||
|
||||
class JobPostingImageForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model=JobPostingImage
|
||||
fields=['post_image']
|
||||
|
||||
class FormTemplateForm(forms.ModelForm):
|
||||
"""Form for creating form templates"""
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
# Generated by Django 5.2.6 on 2025-10-09 10:10
|
||||
# Generated by Django 5.2.7 on 2025-10-11 11:04
|
||||
|
||||
import django.core.validators
|
||||
import django.db.models.deletion
|
||||
import django_ckeditor_5.fields
|
||||
import django_countries.fields
|
||||
import django_extensions.db.fields
|
||||
import recruitment.validators
|
||||
@ -183,7 +184,7 @@ class Migration(migrations.Migration):
|
||||
('slug', django_extensions.db.fields.RandomCharField(blank=True, editable=False, length=8, unique=True, verbose_name='Slug')),
|
||||
('name', models.CharField(help_text='Name of the form template', max_length=200)),
|
||||
('description', models.TextField(blank=True, help_text='Description of the form template')),
|
||||
('is_active', models.BooleanField(default=True, help_text='Whether this template is active')),
|
||||
('is_active', models.BooleanField(default=False, help_text='Whether this template is active')),
|
||||
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='form_templates', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
@ -215,6 +216,7 @@ class Migration(migrations.Migration):
|
||||
('phone', models.CharField(max_length=20, verbose_name='Phone')),
|
||||
('address', models.TextField(max_length=200, verbose_name='Address')),
|
||||
('resume', models.FileField(upload_to='resumes/', verbose_name='Resume')),
|
||||
('is_resume_parsed', models.BooleanField(default=False, verbose_name='Resume Parsed')),
|
||||
('parsed_summary', models.TextField(blank=True, verbose_name='Parsed Summary')),
|
||||
('applied', models.BooleanField(default=False, verbose_name='Applied')),
|
||||
('stage', models.CharField(choices=[('Applied', 'Applied'), ('Exam', 'Exam'), ('Interview', 'Interview'), ('Offer', 'Offer')], default='Applied', max_length=100, verbose_name='Stage')),
|
||||
@ -249,16 +251,16 @@ class Migration(migrations.Migration):
|
||||
('location_city', models.CharField(blank=True, max_length=100)),
|
||||
('location_state', models.CharField(blank=True, max_length=100)),
|
||||
('location_country', models.CharField(default='Saudia Arabia', max_length=100)),
|
||||
('description', models.TextField(help_text='Full job description including responsibilities and requirements')),
|
||||
('qualifications', models.TextField(blank=True, help_text='Required qualifications and skills')),
|
||||
('description', django_ckeditor_5.fields.CKEditor5Field(verbose_name='Description')),
|
||||
('qualifications', django_ckeditor_5.fields.CKEditor5Field(blank=True, null=True)),
|
||||
('salary_range', models.CharField(blank=True, help_text='e.g., $60,000 - $80,000', max_length=200)),
|
||||
('benefits', models.TextField(blank=True, help_text='Benefits offered')),
|
||||
('benefits', django_ckeditor_5.fields.CKEditor5Field(blank=True, null=True)),
|
||||
('application_url', models.URLField(blank=True, help_text='URL where candidates apply', null=True, validators=[django.core.validators.URLValidator()])),
|
||||
('application_deadline', models.DateField(blank=True, null=True)),
|
||||
('application_instructions', models.TextField(blank=True, help_text='Special instructions for applicants')),
|
||||
('application_instructions', django_ckeditor_5.fields.CKEditor5Field(blank=True, null=True)),
|
||||
('internal_job_id', models.CharField(editable=False, max_length=50, primary_key=True, serialize=False)),
|
||||
('created_by', models.CharField(blank=True, help_text='Name of person who created this job', max_length=100)),
|
||||
('status', models.CharField(blank=True, choices=[('DRAFT', 'Draft'), ('PUBLISHED', 'Published'), ('CLOSED', 'Closed'), ('ARCHIVED', 'Archived')], default='DRAFT', max_length=20, null=True)),
|
||||
('status', models.CharField(blank=True, choices=[('DRAFT', 'Draft'), ('ACTIVE', 'Active'), ('CLOSED', 'Closed'), ('CANCELLED', 'Cancelled'), ('ARCHIVED', 'Archived')], default='DRAFT', max_length=20, null=True)),
|
||||
('hash_tags', models.CharField(blank=True, help_text='Comma-separated hashtags for linkedin post like #hiring,#jobopening', max_length=200, validators=[recruitment.validators.validate_hash_tags])),
|
||||
('linkedin_post_id', models.CharField(blank=True, help_text='LinkedIn post ID after posting', max_length=200)),
|
||||
('linkedin_post_url', models.URLField(blank=True, help_text='Direct URL to LinkedIn post')),
|
||||
@ -270,6 +272,9 @@ class Migration(migrations.Migration):
|
||||
('reporting_to', models.CharField(blank=True, help_text='Who this position reports to', max_length=100)),
|
||||
('start_date', models.DateField(blank=True, help_text='Desired start date', null=True)),
|
||||
('open_positions', models.PositiveIntegerField(default=1, help_text='Number of open positions for this job')),
|
||||
('cancel_reason', models.TextField(blank=True, help_text='Reason for canceling the job posting', verbose_name='Cancel Reason')),
|
||||
('cancelled_by', models.CharField(blank=True, help_text='Name of person who cancelled this job', max_length=100, verbose_name='Cancelled By')),
|
||||
('cancelled_at', models.DateTimeField(blank=True, null=True)),
|
||||
('hiring_agency', models.ManyToManyField(blank=True, help_text='External agency responsible for sourcing candidates for this role', related_name='jobs', to='recruitment.hiringagency', verbose_name='Hiring Agency')),
|
||||
('source', models.ForeignKey(blank=True, help_text='The system or channel from which this job posting originated or was first published.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='job_postings', to='recruitment.source')),
|
||||
],
|
||||
@ -312,6 +317,16 @@ class Migration(migrations.Migration):
|
||||
name='job',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='candidates', to='recruitment.jobposting', verbose_name='Job'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='JobPostingImage',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('post_image', models.ImageField(height_field='photo_height', upload_to='post/', width_field='photo_width')),
|
||||
('post_image_height', models.PositiveIntegerField(blank=True, null=True)),
|
||||
('post_image_width', models.PositiveIntegerField(blank=True, null=True)),
|
||||
('job', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='post_images', to='recruitment.jobposting')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Profile',
|
||||
fields=[
|
||||
@ -369,7 +384,7 @@ class Migration(migrations.Migration):
|
||||
('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated at')),
|
||||
('slug', django_extensions.db.fields.RandomCharField(blank=True, editable=False, length=8, unique=True, verbose_name='Slug')),
|
||||
('title', models.CharField(max_length=255, verbose_name='Title')),
|
||||
('content', models.TextField(blank=True, verbose_name='Content')),
|
||||
('content', django_ckeditor_5.fields.CKEditor5Field(blank=True, verbose_name='Content')),
|
||||
('video_link', models.URLField(blank=True, verbose_name='Video Link')),
|
||||
('file', models.FileField(blank=True, upload_to='training_materials/', verbose_name='File')),
|
||||
('created_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='Created by')),
|
||||
|
||||
@ -1,33 +0,0 @@
|
||||
# Generated by Django 5.2.6 on 2025-10-09 10:33
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('recruitment', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='jobposting',
|
||||
name='cancel_reason',
|
||||
field=models.TextField(blank=True, help_text='Reason for canceling the job posting', verbose_name='Cancel Reason'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='jobposting',
|
||||
name='cancelled_at',
|
||||
field=models.DateTimeField(blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='jobposting',
|
||||
name='cancelled_by',
|
||||
field=models.CharField(blank=True, help_text='Name of person who cancelled this job', max_length=100, verbose_name='Cancelled By'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='jobposting',
|
||||
name='status',
|
||||
field=models.CharField(blank=True, choices=[('DRAFT', 'Draft'), ('ACTIVE', 'Active'), ('CLOSED', 'Closed'), ('CANCELLED', 'Cancelled'), ('ARCHIVED', 'Archived')], default='DRAFT', max_length=20, null=True),
|
||||
),
|
||||
]
|
||||
@ -0,0 +1,26 @@
|
||||
# Generated by Django 5.2.7 on 2025-10-11 12:38
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('recruitment', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='jobpostingimage',
|
||||
name='post_image_height',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='jobpostingimage',
|
||||
name='post_image_width',
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='jobpostingimage',
|
||||
name='post_image',
|
||||
field=models.ImageField(upload_to='post/'),
|
||||
),
|
||||
]
|
||||
@ -1,23 +0,0 @@
|
||||
# Generated by Django 5.2.6 on 2025-10-09 12:59
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('recruitment', '0002_jobposting_cancel_reason_jobposting_cancelled_at_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='candidate',
|
||||
name='is_resume_parsed',
|
||||
field=models.BooleanField(default=False, verbose_name='Resume Parsed'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='formtemplate',
|
||||
name='is_active',
|
||||
field=models.BooleanField(default=False, help_text='Whether this template is active'),
|
||||
),
|
||||
]
|
||||
@ -1,30 +0,0 @@
|
||||
# Generated by Django 5.2.7 on 2025-10-10 10:35
|
||||
|
||||
import django.db.models.deletion
|
||||
import django_ckeditor_5.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('recruitment', '0003_candidate_is_resume_parsed_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='jobposting',
|
||||
name='description',
|
||||
field=django_ckeditor_5.fields.CKEditor5Field(help_text='Full job description including responsibilities and requirements'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='JobPostingImage',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('post_image', models.ImageField(height_field='photo_height', upload_to='post/', width_field='photo_width')),
|
||||
('post_image_height', models.PositiveIntegerField(blank=True, null=True)),
|
||||
('post_image_width', models.PositiveIntegerField(blank=True, null=True)),
|
||||
('job', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='post_images', to='recruitment.jobposting')),
|
||||
],
|
||||
),
|
||||
]
|
||||
@ -1,19 +0,0 @@
|
||||
# Generated by Django 5.2.7 on 2025-10-10 10:56
|
||||
|
||||
import django_ckeditor_5.fields
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('recruitment', '0004_alter_jobposting_description_jobpostingimage'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='jobposting',
|
||||
name='description',
|
||||
field=django_ckeditor_5.fields.CKEditor5Field(verbose_name='Description'),
|
||||
),
|
||||
]
|
||||
@ -1,19 +0,0 @@
|
||||
# Generated by Django 5.2.7 on 2025-10-10 11:10
|
||||
|
||||
import django_ckeditor_5.fields
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('recruitment', '0005_alter_jobposting_description'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='jobposting',
|
||||
name='qualifications',
|
||||
field=django_ckeditor_5.fields.CKEditor5Field(blank=True, help_text='Required qualifications and skills'),
|
||||
),
|
||||
]
|
||||
@ -91,7 +91,7 @@ class JobPosting(Base):
|
||||
)
|
||||
benefits = CKEditor5Field(blank=True,null=True,config_name='extends')
|
||||
|
||||
# Application Information
|
||||
# Application Information ---job detail apply link for the candidates
|
||||
application_url = models.URLField(
|
||||
validators=[URLValidator()],
|
||||
help_text="URL where candidates apply",
|
||||
@ -249,11 +249,8 @@ class JobPosting(Base):
|
||||
|
||||
class JobPostingImage(models.Model):
|
||||
job=models.ForeignKey('JobPosting',on_delete=models.CASCADE,related_name='post_images')
|
||||
post_image = models.ImageField(upload_to='post/',
|
||||
height_field='photo_height',
|
||||
width_field='photo_width')
|
||||
post_image_height = models.PositiveIntegerField(null=True, blank=True)
|
||||
post_image_width = models.PositiveIntegerField(null=True, blank=True)
|
||||
post_image = models.ImageField(upload_to='post/')
|
||||
|
||||
|
||||
class Candidate(Base):
|
||||
class Stage(models.TextChoices):
|
||||
@ -409,6 +406,7 @@ class Candidate(Base):
|
||||
return self.STAGE_SEQUENCE.get(old_stage, [])
|
||||
|
||||
@property
|
||||
|
||||
def submission(self):
|
||||
return FormSubmission.objects.filter(template__job=self.job).first()
|
||||
@property
|
||||
|
||||
@ -9,6 +9,7 @@ urlpatterns = [
|
||||
# Job URLs (using JobPosting model)
|
||||
path('jobs/', views_frontend.JobListView.as_view(), name='job_list'),
|
||||
path('jobs/create/', views.create_job, name='job_create'),
|
||||
path('job/<slug:slug>/upload_image_simple/', views.job_image_upload, name='job_image_upload'),
|
||||
path('jobs/<slug:slug>/update/', views.edit_job, name='job_update'),
|
||||
# path('jobs/<slug:slug>/delete/', views., name='job_delete'),
|
||||
path('jobs/<slug:slug>/', views.job_detail, name='job_detail'),
|
||||
@ -66,7 +67,7 @@ urlpatterns = [
|
||||
|
||||
# path('forms/form/<int:template_id>/submit/', views.submit_form, name='submit_form'),
|
||||
# path('forms/form/<int:template_id>/', views.form_wizard_view, name='form_wizard'),
|
||||
path('forms/<int:form_id>/submissions/<int:slug>/', views.form_submission_details, name='form_submission_details'),
|
||||
path('forms/<int:form_id>/submissions/<int:submission_id>/', views.form_submission_details, name='form_submission_details'),
|
||||
path('forms/template/<slug:slug>/submissions/', views.form_template_submissions_list, name='form_template_submissions_list'),
|
||||
|
||||
# path('forms/<int:form_id>/', views.form_preview, name='form_preview'),
|
||||
|
||||
@ -17,6 +17,7 @@ from .forms import (
|
||||
FormTemplateForm,
|
||||
InterviewScheduleForm,JobPostingStatusForm,
|
||||
BreakTimeFormSet,
|
||||
JobPostingImageForm
|
||||
)
|
||||
from rest_framework import viewsets
|
||||
from django.contrib import messages
|
||||
@ -215,6 +216,11 @@ def create_job(request):
|
||||
job.created_by = request.POST.get("created_by", "").strip()
|
||||
if not job.created_by:
|
||||
job.created_by = "University Administrator"
|
||||
|
||||
job.save()
|
||||
job_apply_url_relative=reverse('job_detail_candidate',kwargs={'slug':job.slug})
|
||||
job_apply_url_absolute=request.build_absolute_uri(job_apply_url_relative)
|
||||
job.application_url=job_apply_url_absolute
|
||||
job.save()
|
||||
messages.success(request, f'Job "{job.title}" created successfully!')
|
||||
return redirect("job_list")
|
||||
@ -279,6 +285,7 @@ def job_detail(request, slug):
|
||||
offer_count = candidates.filter(stage="Offer").count()
|
||||
|
||||
status_form = JobPostingStatusForm(instance=job)
|
||||
image_upload_form=JobPostingImageForm(instance=job)
|
||||
|
||||
# 2. Check for POST request (Status Update Submission)
|
||||
if request.method == 'POST':
|
||||
@ -306,10 +313,32 @@ def job_detail(request, slug):
|
||||
"applied_count": applied_count,
|
||||
"interview_count": interview_count,
|
||||
"offer_count": offer_count,
|
||||
'status_form':status_form
|
||||
'status_form':status_form,
|
||||
'image_upload_form':image_upload_form
|
||||
}
|
||||
return render(request, "jobs/job_detail.html", context)
|
||||
|
||||
def job_image_upload(request, slug):
|
||||
#only for handling the post request
|
||||
job=get_object_or_404(JobPosting,slug=slug)
|
||||
if request.method=='POST':
|
||||
image_upload_form=JobPostingImageForm(request.POST,request.FILES)
|
||||
if image_upload_form.is_valid():
|
||||
image_upload_form = image_upload_form.save(commit=False)
|
||||
|
||||
image_upload_form.job = job
|
||||
image_upload_form.save()
|
||||
messages.success(request, f"Image uploaded successfully for {job.title}.")
|
||||
return redirect('job_detail', slug=job.slug)
|
||||
else:
|
||||
|
||||
messages.error(request, "Image upload failed: Please ensure a valid image file was selected.")
|
||||
|
||||
return redirect('job_detail', slug=job.slug)
|
||||
return redirect('job_detail', slug=job.slug)
|
||||
|
||||
|
||||
|
||||
|
||||
# job detail facing the candidate:
|
||||
def job_detail_candidate(request, slug):
|
||||
|
||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 23 KiB |
@ -364,14 +364,14 @@
|
||||
.add-option {
|
||||
color: var(--primary);
|
||||
cursor: pointer;
|
||||
font-size: 0.9rem;
|
||||
font-size: 1rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
.add-option:hover {
|
||||
text-decoration: underline;
|
||||
text-decoration: none;
|
||||
}
|
||||
/* File Upload Specific Styles */
|
||||
.file-upload-area {
|
||||
@ -685,12 +685,10 @@
|
||||
<div class="container">
|
||||
<!-- Sidebar with form elements -->
|
||||
<div class="sidebar">
|
||||
<div class="sidebar-header">
|
||||
<a class="" href="{% url 'form_templates_list' %}">
|
||||
<img src="{% static 'image/kaauh.jpeg' %}" style="height:100px; width:100px;">
|
||||
|
||||
<div class="sidebar-header" style="display: flex; flex-direction: column; align-items: center; justify-content: center;">
|
||||
<a href="{% url 'form_templates_list' %}">
|
||||
<img src="{% static 'image/kaauh.jpeg' %}" style="height:100px; width:100px; display: block; margin: 0 auto;">
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<div class="field-categories">
|
||||
<div class="field-category">
|
||||
|
||||
@ -231,10 +231,10 @@
|
||||
<td>{{ submission.applicant_email|default:"N/A" }}</td>
|
||||
<td>{{ submission.submitted_at|date:"M d, Y H:i" }}</td>
|
||||
<td class="text-end">
|
||||
<a href="{% url 'form_submission_details' template_id=template.id submission_id=submission.id %}" class="btn btn-sm btn-outline-primary">
|
||||
<a href="{% url 'form_submission_details' template_id=template.id submission_id=submission.id %}" class="btn btn-sm btn-outline-primary">
|
||||
<i class="fas fa-eye me-1"></i> {% trans "View Details" %}
|
||||
</a>
|
||||
</td>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
||||
@ -505,7 +505,7 @@
|
||||
<body>
|
||||
<nav
|
||||
id="topNavbar"
|
||||
class="navbar navbar-expand-lg sticky-top"
|
||||
class="navbar navbar-expand-lg"
|
||||
style="background-color: white; z-index: 1030"
|
||||
>
|
||||
<div class="container-fluid">
|
||||
|
||||
@ -193,14 +193,14 @@
|
||||
{% if form.salary_range.errors %}<div class="text-danger small mt-1">{{ form.salary_range.errors }}</div>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
{% comment %} <div class="col-md-6">
|
||||
<div>
|
||||
<label for="{{ form.application_url.id_for_label }}" class="form-label">{% trans "Application URL" %} <span class="text-danger">*</span></label>
|
||||
{{ form.application_url }}
|
||||
{% if form.application_url.errors %}<div class="text-danger small mt-1">{{ form.application_url.errors }}</div>{% endif %}
|
||||
<div class="form-text">{% trans "Full URL where candidates will apply" %}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> {% endcomment %}
|
||||
|
||||
<div class="col-12">
|
||||
<div>
|
||||
|
||||
@ -199,14 +199,14 @@
|
||||
{% if form.salary_range.errors %}<div class="text-danger small mt-1">{{ form.salary_range.errors }}</div>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
{% comment %} <div class="col-md-6">
|
||||
<div>
|
||||
<label for="{{ form.application_url.id_for_label }}" class="form-label">{% trans "Application URL" %} <span class="text-danger">*</span></label>
|
||||
{{ form.application_url }}
|
||||
{% if form.application_url.errors %}<div class="text-danger small mt-1">{{ form.application_url.errors }}</div>{% endif %}
|
||||
<div class="form-text">{% trans "Full URL where candidates will apply" %}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> {% endcomment %}
|
||||
|
||||
<div class="col-12">
|
||||
<div>
|
||||
|
||||
@ -409,11 +409,11 @@
|
||||
<i class="fas fa-edit"></i> {% trans "Edit Job" %}
|
||||
</a>
|
||||
|
||||
{% if job.application_url %}
|
||||
|
||||
<button type="button" class="btn btn-outline-secondary" data-bs-toggle="modal" data-bs-target="#myModalForm">
|
||||
<i class="fas fa-image me-1"></i> {% trans "Upload Image for Post" %}
|
||||
</button>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -590,7 +590,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">{% trans "Cancel" %}</button>
|
||||
<button type="button" class="btn btn-outline-secondary btn-lg" data-bs-dismiss="modal">{% trans "Cancel" %}</button>
|
||||
<button type="submit" class="btn btn-main-action">{% trans "Save Changes" %}</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@ -246,7 +246,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{job.form_template}}
|
||||
|
||||
<div class="mobile-fixed-apply-bar d-lg-none">
|
||||
{% if job.form_template %}
|
||||
<a href="{% url 'form_wizard' job.form_template.pk %}" class="btn btn-main-action btn-lg w-100">
|
||||
|
||||
@ -1,17 +1,22 @@
|
||||
<div class="modal fade" id="myModalForm" tabindex="-1" aria-labelledby="myModalLabel" aria-hidden="true">
|
||||
<div class="modal fade mt-4" id="myModalForm" tabindex="-1" aria-labelledby="myModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="myModalLabel">Add New Image</h5>
|
||||
<h5 class="modal-title" id="myModalLabel">Add New Image for the Post</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form method="post" action="{% url 'job_detail' job.slug %}">
|
||||
<form method="post" action="{% url 'job_image_upload' job.slug %}" enctype="multipart/form-data" >
|
||||
{% csrf_token %}
|
||||
{{ image_form }}
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||
<button type="submit" class="btn btn-primary">Save changes</button>
|
||||
{{ image_upload_form.as_p}}
|
||||
|
||||
{% if image_upload_form.instance.post_image %}
|
||||
<p>Current Image:</p>
|
||||
<img src="{{ image_upload_form.instance.post_image.url }}" alt="Post Image" style="max-width: 200px;">
|
||||
{% endif %}
|
||||
<div class="modal-footer mt-2">
|
||||
<button type="button" class="btn btn-lg btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||
<button type="submit" class="btn btn-main-action ">Save changes</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user