From 6a979df528f3005a17a800fb3c8e1d9d3932fd02 Mon Sep 17 00:00:00 2001 From: Ali Nabhan Aboobakuru <Ali3.Aboobakuru@live.uwe.ac.uk> Date: Wed, 23 Oct 2024 11:31:31 +0500 Subject: [PATCH] Added comments to most of the code that I edited. --- postgresTest/PROJECT1/forms.py | 102 +++++++++--------- postgresTest/PROJECT1/templates/base.html | 55 ++++++---- .../PROJECT1/templates/employee_details.html | 101 ++++++++++++++++- .../PROJECT1/templates/manage_consent.html | 23 +++- .../PROJECT1/templates/onboard_employee.html | 73 +++++++++++-- .../PROJECT1/templates/request_consent.html | 28 ++++- postgresTest/PROJECT1/templates/settings.html | 35 +++--- postgresTest/PROJECT1/urls.py | 97 ++++++++++------- 8 files changed, 376 insertions(+), 138 deletions(-) diff --git a/postgresTest/PROJECT1/forms.py b/postgresTest/PROJECT1/forms.py index 89886cf0..dc0c63b0 100644 --- a/postgresTest/PROJECT1/forms.py +++ b/postgresTest/PROJECT1/forms.py @@ -1,5 +1,3 @@ -# forms.py - from django import forms from django.contrib.auth.forms import UserCreationForm from django.contrib.auth import get_user_model @@ -8,21 +6,22 @@ from django.core.validators import RegexValidator, EmailValidator from django.core.exceptions import ValidationError import datetime +# PrivacyForm: Allows employees to update privacy settings (like whether their profile can be accessed by the public) class PrivacyForm(forms.ModelForm): class Meta: - model = Employee - fields = ['allow_public_access'] # Only allow updating the privacy checkbox + model = Employee # Uses the Employee model + fields = ['allow_public_access'] # Only allows updating the 'allow_public_access' field widgets = { - 'allow_public_access': forms.CheckboxInput(attrs={'class': 'form-check-input'}) + 'allow_public_access': forms.CheckboxInput(attrs={'class': 'form-check-input'}) # Render as a checkbox with Bootstrap class } -# RoleAssignmentForm for assigning roles +# RoleAssignmentForm: Assigns roles (Admin, HR, Employee, etc.) to a user class RoleAssignmentForm(forms.ModelForm): class Meta: - model = CustomUser - fields = ['role'] + model = CustomUser # Uses the CustomUser model + fields = ['role'] # Only the 'role' field can be updated widgets = { - 'role': forms.Select(choices=[ + 'role': forms.Select(choices=[ # Renders the 'role' field as a select dropdown with different role options ('Admin', 'Administrator'), ('HR', 'HR Staff'), ('Manager', 'Employee Manager'), @@ -30,23 +29,23 @@ class RoleAssignmentForm(forms.ModelForm): ]) } -# CustomUserCreationForm for creating users with role and validation +# CustomUserCreationForm: Customizes the user registration form to include email validation class CustomUserCreationForm(UserCreationForm): email = forms.EmailField( - required=True, - widget=forms.EmailInput(attrs={'class': 'form-control', 'placeholder': 'Email'}), - validators=[EmailValidator(message="Enter a valid email address.")] + required=True, # Email is required + widget=forms.EmailInput(attrs={'class': 'form-control', 'placeholder': 'Email'}), # Custom widget for email input + validators=[EmailValidator(message="Enter a valid email address.")] # Ensures valid email format ) class Meta(UserCreationForm.Meta): - model = get_user_model() - fields = UserCreationForm.Meta.fields + ('email',) # Ensure email is included in the form + model = get_user_model() # Uses the default user model + fields = UserCreationForm.Meta.fields + ('email',) # Extends the default fields with 'email' -# ContactForm with custom validation and widgets for collecting contact info +# ContactForm: Collects basic contact information with custom validation for phone number class ContactForm(forms.ModelForm): class Meta: - model = Contact - fields = ['name', 'phone', 'email', 'message'] + model = Contact # Uses the Contact model + fields = ['name', 'phone', 'email', 'message'] # Fields that are displayed in the form widgets = { 'name': forms.TextInput(attrs={'placeholder': 'Your Name', 'required': True, 'class': 'form-control'}), 'phone': forms.TextInput(attrs={'placeholder': 'Phone Number', 'required': True, 'class': 'form-control'}), @@ -54,39 +53,40 @@ class ContactForm(forms.ModelForm): 'message': forms.Textarea(attrs={'placeholder': 'Message', 'required': True, 'class': 'form-control message-box'}), } - # Additional validation for phone number to ensure proper format + # Validation for phone number def clean_phone(self): - phone = self.cleaned_data.get('phone') + phone = self.cleaned_data.get('phone') # Gets the phone field data phone_validator = RegexValidator( - regex=r'^\+?1?\d{9,15}$', + regex=r'^\+?1?\d{9,15}$', # Validates phone format (e.g., +123456789) message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed." ) - phone_validator(phone) - return phone + phone_validator(phone) # Applies the validation + return phone # Returns cleaned phone data -# OnboardingForm with custom widgets and validation for employee onboarding +# OnboardingForm: Handles onboarding for employees, including documents like ID, CV, police report class OnboardingForm(forms.ModelForm): police_report = forms.FileField( - required=True, + required=True, # Police report is mandatory label="Police Report", - widget=forms.ClearableFileInput(attrs={'accept': '.pdf'}) + widget=forms.ClearableFileInput(attrs={'accept': '.pdf'}) # Accepts only PDF files ) id_card_front = forms.ImageField( - required=True, + required=True, # ID front is required label="ID Card (Front)", - widget=forms.ClearableFileInput(attrs={'accept': 'image/png, image/jpeg'}) + widget=forms.ClearableFileInput(attrs={'accept': 'image/png, image/jpeg'}) # Accepts PNG or JPEG images ) id_card_back = forms.ImageField( - required=True, + required=True, # ID back is required label="ID Card (Back)", - widget=forms.ClearableFileInput(attrs={'accept': 'image/png, image/jpeg'}) + widget=forms.ClearableFileInput(attrs={'accept': 'image/png, image/jpeg'}) # Accepts PNG or JPEG images ) cv = forms.FileField( - required=True, + required=True, # CV is required label="CV (Resume)", - widget=forms.ClearableFileInput(attrs={'accept': '.pdf'}) + widget=forms.ClearableFileInput(attrs={'accept': '.pdf'}) # Accepts only PDF files ) + # Textarea for entering a list of skills skills = forms.CharField( required=True, widget=forms.Textarea(attrs={'class': 'form-control', 'placeholder': 'List of skills...'}), @@ -94,12 +94,12 @@ class OnboardingForm(forms.ModelForm): ) class Meta: - model = Employee + model = Employee # Uses the Employee model fields = [ - 'first_name', 'last_name', 'email', 'phone', 'address', - 'department', 'job_title', 'start_date', 'date_of_birth', - 'id_card_number', 'emergency_contact_name', 'emergency_contact_phone', - 'banking_information', 'police_report', 'id_card_front', 'id_card_back', 'cv', 'skills','allow_public_access' + 'first_name', 'last_name', 'email', 'phone', 'address', 'department', 'job_title', + 'start_date', 'date_of_birth', 'id_card_number', 'emergency_contact_name', + 'emergency_contact_phone', 'banking_information', 'police_report', 'id_card_front', + 'id_card_back', 'cv', 'skills', 'allow_public_access' # Fields included in the form ] widgets = { 'first_name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'First Name'}), @@ -109,38 +109,37 @@ class OnboardingForm(forms.ModelForm): 'address': forms.Textarea(attrs={'class': 'form-control', 'placeholder': 'Residential Address'}), 'department': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Department'}), 'job_title': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Job Title'}), - 'start_date': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}), + 'start_date': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}), # Date input widget 'date_of_birth': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}), 'id_card_number': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'ID Card Number'}), 'emergency_contact_name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Emergency Contact Name'}), 'emergency_contact_phone': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Emergency Contact Phone'}), 'banking_information': forms.Textarea(attrs={'class': 'form-control', 'placeholder': 'Banking Information (optional)'}), - 'allow_public_access': forms.CheckboxInput(attrs={'class': 'form-check-input'}) + 'allow_public_access': forms.CheckboxInput(attrs={'class': 'form-check-input'}) # Checkbox widget for privacy setting } - - # Additional validation for email + # Custom email validation def clean_email(self): - email = self.cleaned_data.get('email') + email = self.cleaned_data.get('email') # Gets the email data email_validator = EmailValidator(message="Enter a valid email address.") - email_validator(email) + email_validator(email) # Validates email format return email - # Additional validation for start date + # Custom validation for start date to ensure it is not in the future def clean_start_date(self): start_date = self.cleaned_data.get('start_date') if start_date > datetime.date.today(): raise forms.ValidationError("Start date cannot be in the future.") return start_date - # Additional validation for date of birth + # Custom validation for date of birth to ensure it is in the past def clean_date_of_birth(self): date_of_birth = self.cleaned_data.get('date_of_birth') if date_of_birth >= datetime.date.today(): raise forms.ValidationError("Date of birth must be in the past.") return date_of_birth - # Validation for phone number + # Custom phone number validation def clean_phone(self): phone = self.cleaned_data.get('phone') phone_validator = RegexValidator( @@ -160,7 +159,7 @@ class OnboardingForm(forms.ModelForm): phone_validator(emergency_contact_phone) return emergency_contact_phone - # Server-side validation for file types + # Validation for file type of the police report (must be PDF) def clean_police_report(self): police_report = self.cleaned_data.get('police_report') if police_report: @@ -168,6 +167,7 @@ class OnboardingForm(forms.ModelForm): raise ValidationError("Police Report must be a PDF file.") return police_report + # Validation for file type of the CV (must be PDF) def clean_cv(self): cv = self.cleaned_data.get('cv') if cv: @@ -175,6 +175,7 @@ class OnboardingForm(forms.ModelForm): raise ValidationError("CV must be a PDF file.") return cv + # Validation for file type of ID Card (Front) (must be PNG or JPG) def clean_id_card_front(self): id_card_front = self.cleaned_data.get('id_card_front') if id_card_front: @@ -182,6 +183,7 @@ class OnboardingForm(forms.ModelForm): raise ValidationError("ID Card Front must be a PNG or JPG image.") return id_card_front + # Validation for file type of ID Card (Back) (must be PNG or JPG) def clean_id_card_back(self): id_card_back = self.cleaned_data.get('id_card_back') if id_card_back: @@ -189,7 +191,7 @@ class OnboardingForm(forms.ModelForm): raise ValidationError("ID Card Back must be a PNG or JPG image.") return id_card_back -### New CompanyOnboardingForm for companies ### +# CompanyOnboardingForm: Handles onboarding for companies class CompanyOnboardingForm(forms.ModelForm): registration_number = forms.CharField( required=True, @@ -218,5 +220,5 @@ class CompanyOnboardingForm(forms.ModelForm): ) class Meta: - model = Company # Now the form is using the Company model instead of CustomUser - fields = ['registration_number', 'contact_person', 'contact_email', 'phone', 'address'] + model = Company # The form is linked to the Company model + fields = ['registration_number', 'contact_person', 'contact_email', 'phone', 'address'] # Fields included in the form diff --git a/postgresTest/PROJECT1/templates/base.html b/postgresTest/PROJECT1/templates/base.html index 91f90d15..f20fdecc 100644 --- a/postgresTest/PROJECT1/templates/base.html +++ b/postgresTest/PROJECT1/templates/base.html @@ -13,10 +13,10 @@ <!-- Favicon --> <link rel="icon" href="{% static 'images/fevicon/fevicon.png' %}" type="image/gif" /> - <!-- Title --> + <!-- Title block that allows page-specific titles --> <title>{% block title %}HR System Onboarding{% endblock %}</title> - <!-- Stylesheets --> + <!-- Stylesheets (Bootstrap, Google Fonts, and Custom Styles) --> <link rel="stylesheet" type="text/css" href="{% static 'css/bootstrap.css' %}" /> <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700;900&display=swap" rel="stylesheet"> <link href="{% static 'css/font-awesome.min.css' %}" rel="stylesheet" /> @@ -24,7 +24,7 @@ <link href="{% static 'css/responsive.css' %}" rel="stylesheet" /> <style> - /* Custom CSS for the toggling effect */ + /* Styling for the collapsible sidebar and page layout */ .wrapper { display: flex; width: 100%; @@ -35,18 +35,18 @@ width: 250px; transition: all 0.3s; position: fixed; - top: 60px; /* Adjust this value based on the height of your header */ + top: 60px; /* Adjust based on header height */ bottom: 0; left: 0; } .sidebar-wrapper.collapsed { - margin-left: -250px; + margin-left: -250px; /* Collapse sidebar */ } .page-content-wrapper { margin-left: 250px; - width: calc(100% - 250px); + width: calc(100% - 250px); /* Main content width adjusts with sidebar */ transition: all 0.3s; padding: 20px; background-color: #f7f7f7; @@ -54,11 +54,11 @@ } .toggled .sidebar-wrapper { - margin-left: -250px; + margin-left: -250px; /* When toggled, sidebar collapses */ } .toggled .page-content-wrapper { - margin-left: 0; + margin-left: 0; /* Content becomes full width when sidebar is collapsed */ width: 100%; } @@ -68,6 +68,7 @@ margin: 10px; } + /* Styling for sidebar links with icons */ .sidebar-wrapper .list-group-item { display: flex; align-items: center; @@ -77,7 +78,7 @@ margin-right: 10px; } - /* Onboarding-specific styles */ + /* Specific styling for onboarding steps and header */ .onboarding-header { font-size: 28px; font-weight: 700; @@ -115,7 +116,7 @@ margin-top: 20px; } - /* Custom CSS for the login icon in the top right corner */ + /* Custom CSS for the login icon at the top right corner */ .login-icon { position: absolute; top: 10px; @@ -131,6 +132,7 @@ <header class="header_section"> <div class="container-fluid"> <nav class="navbar navbar-expand-lg custom_nav-container"> + <!-- Logo/Title linking to homepage --> <a class="navbar-brand" href="{% url 'home' %}"> <span>HR Onboarding</span> </a> @@ -147,7 +149,7 @@ <!-- Collapsible Sidebar --> <div class="sidebar-wrapper bg-light border-right" id="sidebar-wrapper"> <div class="list-group list-group-flush"> - <!-- Links specifically for onboarding --> + <!-- Sidebar links for onboarding, employees, company, settings, and reports --> <a href="{% url 'onboard_employee' %}" class="list-group-item list-group-item-action bg-light"> <i class="fa fa-user-plus" aria-hidden="true"></i> Onboard Employee </a> @@ -173,43 +175,60 @@ <!-- Main content area --> <div class="page-content-wrapper" id="page-content-wrapper"> + <!-- Toggle icon for collapsing the sidebar --> <i class="fa fa-bars toggle-icon" id="menu-toggle"></i> <div class="container-fluid"> <div class="onboarding-header"> - <!-- Remove this second block title --> + <!-- Main heading for onboarding --> <h1>Welcome to HR Onboarding</h1> + + <!-- User Role Display --> + <!-- Displays the username and role (if available) --> + {% if request.user.is_authenticated %} + <p> + Logged in as: {{ request.user.username }} + {% if request.user.role %} + ({{ request.user.get_role_display }}) + {% endif %} + </p> + {% else %} + <p>Not logged in</p> + {% endif %} </div> + <!-- Placeholder content for onboarding steps --> <div class="onboarding-content"> {% block content %} - <!-- Content such as onboarding steps, forms, etc. will be injected here --> + <!-- Step 1 --> <div class="onboarding-step"> <h4>Step 1: Complete Your Profile</h4> <p>Please provide all the necessary personal information to complete your profile.</p> </div> + <!-- Step 2 --> <div class="onboarding-step"> <h4>Step 2: Review Company Policies</h4> <p>Make sure to go through the company policies to understand our code of conduct.</p> </div> + <!-- Proceed Button --> <a href="#" class="btn-next">Proceed to the Next Step</a> {% endblock content %} </div> </div> </div> - <!-- jQuery --> + <!-- JavaScript for handling sidebar and other interactivity --> <script type="text/javascript" src="{% static 'js/jquery-3.4.1.min.js' %}"></script> - <!-- popper js --> + <!-- popper js for tooltips and popovers --> <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"></script> - <!-- bootstrap js --> + <!-- Bootstrap JS for general interactivity --> <script type="text/javascript" src="{% static 'js/bootstrap.js' %}"></script> - <!-- custom js --> + <!-- Custom JS for any additional functionality --> <script type="text/javascript" src="{% static 'js/custom.js' %}"></script> <script> - // Toggle sidebar + // Toggle sidebar functionality $("#menu-toggle").click(function(e) { e.preventDefault(); $("#sidebar-wrapper").toggleClass("collapsed"); diff --git a/postgresTest/PROJECT1/templates/employee_details.html b/postgresTest/PROJECT1/templates/employee_details.html index e4ea45b5..a98b94fe 100644 --- a/postgresTest/PROJECT1/templates/employee_details.html +++ b/postgresTest/PROJECT1/templates/employee_details.html @@ -1,32 +1,129 @@ {% extends 'base.html' %} +<!-- Inherit layout and styles from the base.html template --> + {% load static %} +<!-- Load static files like images, CSS, or JS for use in the template --> + {% block title %} Employee Details {% endblock title %} +<!-- Set the title of the page to "Employee Details", which will be inserted into the 'title' block in base.html --> {% block content %} +<!-- Start of the main content block --> + <div class="container mt-5"> + <!-- Main container for the employee details page, with margin-top set to 5 units --> + <h2>Employee Details</h2> + <!-- Page heading --> + <hr> + <!-- Horizontal line for visual separation --> <div class="row"> + <!-- Use Bootstrap grid system to split the page into two equal columns --> + <div class="col-md-6"> + <!-- First column for personal information --> <h4>Personal Information</h4> + <!-- Subheading for personal info --> <p><strong>First Name:</strong> {{ employee.first_name }}</p> + <!-- Display the employee's first name --> <p><strong>Last Name:</strong> {{ employee.last_name }}</p> + <!-- Display the employee's last name --> <p><strong>Email:</strong> {{ employee.email }}</p> + <!-- Display the employee's email address --> <p><strong>Phone:</strong> {{ employee.phone }}</p> + <!-- Display the employee's phone number --> + <p><strong>Address:</strong> {{ employee.address }}</p> + <!-- Display the employee's address --> + <p><strong>Date of Birth:</strong> {{ employee.date_of_birth }}</p> + <!-- Display the employee's date of birth --> </div> - + <div class="col-md-6"> + <!-- Second column for work-related information --> <h4>Work Information</h4> + <!-- Subheading for work info --> <p><strong>Department:</strong> {{ employee.department }}</p> + <!-- Display the department the employee works in --> <p><strong>Job Title:</strong> {{ employee.job_title }}</p> + <!-- Display the employee's job title --> + <p><strong>Start Date:</strong> {{ employee.start_date }}</p> + <!-- Display the employee's start date --> <p><strong>Role:</strong> {{ employee.get_role_display }}</p> + <!-- Display the role using the display value, as defined in the choices in the model --> + <p><strong>Banking Information:</strong> {{ employee.banking_information }}</p> + <!-- Display the employee's banking information, if provided --> </div> </div> - + + <hr> + <!-- Horizontal line to separate sections --> + + <!-- Work Experience --> + <h4>Work Experience</h4> + <!-- Subheading for work experience --> + <p><strong>Job Description:</strong> {{ employee.job_description }}</p> + <!-- Display the employee's job description --> + <p><strong>End Date:</strong> {{ employee.end_date }}</p> + <!-- Display the employee's end date, if applicable --> + + <hr> + <!-- Horizontal line to separate sections --> + + <!-- Emergency Contact Information --> + <h4>Emergency Contact</h4> + <!-- Subheading for emergency contact information --> + <p><strong>Contact Name:</strong> {{ employee.emergency_contact_name }}</p> + <!-- Display the emergency contact's name --> + <p><strong>Contact Phone:</strong> {{ employee.emergency_contact_phone }}</p> + <!-- Display the emergency contact's phone number --> + + <hr> + <!-- Horizontal line to separate sections --> + + <!-- ID Information --> + <h4>ID Information</h4> + <!-- Subheading for ID information --> + <p><strong>ID Card Number:</strong> {{ employee.id_card_number }}</p> + <!-- Display the employee's ID card number --> + <div> + <p><strong>ID Card Front:</strong></p> + <img src="{{ employee.id_card_front.url }}" alt="ID Card Front" class="img-thumbnail" width="150"> + <!-- Display the image of the front of the employee's ID card --> + </div> + <div> + <p><strong>ID Card Back:</strong></p> + <img src="{{ employee.id_card_back.url }}" alt="ID Card Back" class="img-thumbnail" width="150"> + <!-- Display the image of the back of the employee's ID card --> + </div> + <hr> + <!-- Horizontal line to separate sections --> + + <!-- Documents Section --> + <h4>Documents</h4> + <!-- Subheading for employee documents --> + <p><strong>CV (Resume):</strong> <a href="{{ employee.cv.url }}" target="_blank">Download CV</a></p> + <!-- Provide a link to download the employee's CV (resume) --> + <p><strong>Police Report:</strong> <a href="{{ employee.police_report.url }}" target="_blank">Download Police Report</a></p> + <!-- Provide a link to download the employee's police report --> + + <hr> + <!-- Horizontal line to separate sections --> + + <!-- Privacy Options --> + <h4>Privacy Options</h4> + <!-- Subheading for privacy settings --> + <p><strong>Allow Public Access:</strong> {{ employee.allow_public_access|yesno:"Yes,No" }}</p> + <!-- Display whether public access to the employee's profile is allowed, using the "yesno" filter for Boolean fields --> + + <hr> + <!-- Horizontal line to separate sections --> + <a href="{% url 'employee_list' %}" class="btn btn-secondary">Back to Employee List</a> + <!-- Button to return to the employee list --> </div> {% endblock content %} diff --git a/postgresTest/PROJECT1/templates/manage_consent.html b/postgresTest/PROJECT1/templates/manage_consent.html index 532279f5..b379c284 100644 --- a/postgresTest/PROJECT1/templates/manage_consent.html +++ b/postgresTest/PROJECT1/templates/manage_consent.html @@ -1,28 +1,47 @@ {% extends 'base.html' %} +<!-- This template extends the 'base.html' layout, inheriting all its structure and design --> + {% block title %}Manage Consent Requests{% endblock title %} +<!-- The title block is overridden here with "Manage Consent Requests" to set the page title --> {% block content %} +<!-- Main content block where specific page content is injected --> + <h1>Manage Consent Requests</h1> +<!-- Header for the page --> <div class="container"> + <!-- Main container for the content, typically used for Bootstrap layout to create padding and structure --> + <p>You have a request from a company to view your personal information.</p> - - <!-- Consent form to approve or deny the request --> + <!-- Informational text explaining to the user that a company has requested access to their personal information --> + + <!-- Form to approve or deny the consent request --> <form method="POST"> {% csrf_token %} + <!-- CSRF token for protection against cross-site request forgery attacks --> + <div class="form-group"> + <!-- Form group for the buttons --> <button type="submit" name="approve" class="btn btn-success">Approve</button> + <!-- Button for approving the request. The `name="approve"` allows backend logic to detect which button was pressed --> + <button type="submit" name="deny" class="btn btn-danger">Deny</button> + <!-- Button for denying the request. The `name="deny"` allows backend logic to detect the deny action --> </div> </form> <!-- Messages --> {% if messages %} <div class="alert alert-info"> + <!-- If there are any messages, display them inside an alert box styled with Bootstrap's "alert-info" class --> {% for message in messages %} {{ message }} + <!-- Iterate over each message in the messages list and display it --> {% endfor %} </div> {% endif %} </div> + {% endblock content %} +<!-- End of the content block where the main content of the page is injected --> diff --git a/postgresTest/PROJECT1/templates/onboard_employee.html b/postgresTest/PROJECT1/templates/onboard_employee.html index 4ee5272c..36aedeec 100644 --- a/postgresTest/PROJECT1/templates/onboard_employee.html +++ b/postgresTest/PROJECT1/templates/onboard_employee.html @@ -1,21 +1,30 @@ {% extends 'base.html' %} +<!-- This template extends 'base.html', inheriting its layout structure and styles --> + {% load custom_filters %} +<!-- Custom filters are being loaded here, possibly for processing or displaying data --> + {% load static %} +<!-- Static files (CSS, JS, images) are being loaded for use in the template --> {% block title %} Onboard New Employee {% endblock title %} +<!-- The title of the page is set to "Onboard New Employee", which will replace the title block in base.html --> {% block content %} +<!-- Start of the main content block for the onboarding form --> + <style> - /* General Settings */ + /* General page settings for body font and background */ body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; background-color: #f5f5f5; margin: 0; padding: 20px; } - /* Container Styles */ + + /* Container for the entire CV form */ .cv-container { display: flex; max-width: 1000px; @@ -25,7 +34,8 @@ Onboard New Employee box-shadow: 0 0 20px rgba(0, 0, 0, 0.1); overflow: hidden; } - /* Sidebar Styling */ + + /* Styling for the sidebar (left section) */ .cv-sidebar { width: 30%; background-color: #417690; @@ -33,10 +43,14 @@ Onboard New Employee padding: 30px; box-sizing: border-box; } + + /* Styling for the photo section in the sidebar */ .cv-photo { text-align: center; margin-bottom: 20px; } + + /* Styling for the profile image */ .cv-photo img { width: 150px; height: 150px; @@ -44,9 +58,13 @@ Onboard New Employee display: block; margin: 0 auto 10px auto; } + + /* File input for photo upload, hidden by default */ .cv-photo input[type="file"] { display: none; } + + /* Button to trigger the photo upload */ .cv-photo button { background-color: #27ae60; color: #ffffff; @@ -55,11 +73,15 @@ Onboard New Employee border-radius: 5px; cursor: pointer; } + + /* Section headings in the sidebar */ .cv-sidebar h3 { margin-top: 30px; border-bottom: 2px solid #f5dd5d; padding-bottom: 5px; } + + /* Inputs in the sidebar for contact, education, and skills */ .cv-sidebar input, .cv-sidebar textarea { width: 100%; padding: 10px; @@ -70,26 +92,33 @@ Onboard New Employee color: #333; box-sizing: border-box; } - /* Main Content Styling */ + + /* Main content section (right side of the form) */ .cv-main { width: 70%; padding: 40px; box-sizing: border-box; } + + /* Header styles for the main form */ .cv-main h1 { font-size: 2rem; font-weight: bold; color: #333; margin-bottom: 5px; } + .cv-main h2 { font-size: 1.25rem; color: #f5dd5d; margin-bottom: 30px; } + + /* Section for each part of the form (e.g., Profile, Work Experience, etc.) */ .cv-section { margin-bottom: 40px; } + .cv-section h3 { font-size: 1.1rem; color: #333; @@ -97,16 +126,20 @@ Onboard New Employee padding-bottom: 10px; margin-bottom: 20px; } + + /* Form group styling for labels and inputs */ .form-group { margin-bottom: 15px; display: flex; flex-direction: column; } + .form-group label { font-weight: 500; margin-bottom: 5px; color: #666; } + .form-group input, .form-group textarea, .form-group select { @@ -116,6 +149,8 @@ Onboard New Employee border-radius: 5px; background-color: #f8f8f8; } + + /* Styling for the submit button */ .btn-primary { background-color: #27ae60; color: #ffffff; @@ -129,15 +164,19 @@ Onboard New Employee cursor: pointer; transition: background-color 0.3s; } + .btn-primary:hover { background-color: #219150; } + + /* Styling for error messages */ .error-message { color: red; font-size: 0.875rem; margin-top: 5px; } - /* Responsive Styles */ + + /* Responsive design for mobile devices */ @media (max-width: 768px) { .cv-container { flex-direction: column; @@ -154,42 +193,54 @@ Onboard New Employee </style> <div class="cv-container"> + <!-- Sidebar for employee's photo, contact, and education info --> <div class="cv-sidebar"> <div class="cv-photo"> <img id="profile-picture" src="{% static 'images/profile_placeholder.png' %}" alt="Profile Photo"> + <!-- Hidden file input for uploading profile photo --> <input type="file" id="profile-upload" accept="image/*"> <button type="button" onclick="document.getElementById('profile-upload').click();">Upload Photo</button> </div> + <!-- Contact information form fields --> <h3>CONTACT</h3> <input type="text" name="phone" placeholder="Phone Number" value="{{ form.phone.value }}"> <input type="email" name="email" placeholder="Email Address" value="{{ form.email.value }}"> <textarea name="address" placeholder="Residential Address">{{ form.address.value }}</textarea> - + + <!-- Education information form fields --> <h3>EDUCATION</h3> <input type="text" name="institution" placeholder="Institution" value="{{ form.institution.value }}"> <input type="text" name="degree" placeholder="Highest Degree" value="{{ form.degree.value }}"> + <!-- Skills information form fields --> <h3>SKILLS</h3> <input type="text" name="skill_1" placeholder="Skill 1"> <input type="text" name="skill_2" placeholder="Skill 2"> <input type="text" name="skill_3" placeholder="Skill 3"> </div> + <!-- Main content area for the form --> <form method="POST" enctype="multipart/form-data" class="cv-main"> {% csrf_token %} + <!-- CSRF token for form security --> + + <!-- Employee details form fields --> <h1>{{ form.first_name }} {{ form.last_name }}</h1> <h2>{{ form.job_title }}</h2> + <!-- Profile section --> <section class="cv-section"> <h3>PROFILE</h3> <p>Provide a summary or objectives for the employee.</p> </section> + <!-- Work experience section --> <section class="cv-section"> <h3>WORK EXPERIENCE</h3> <div class="form-group"> {{ form.start_date.label_tag }} {{ form.start_date }} + <!-- Error messages for start date if validation fails --> {% if form.start_date.errors %} <div class="error-message"> {% for error in form.start_date.errors %} @@ -198,16 +249,19 @@ Onboard New Employee </div> {% endif %} </div> + <!-- End date input --> <div class="form-group"> <label for="end_date">End Date</label> <input type="date" id="end_date" name="end_date" class="form-control"> </div> + <!-- Job description input --> <div class="form-group"> <label for="job_description">Job Description</label> <textarea id="job_description" name="job_description" class="form-control" placeholder="What did you do in this job?"></textarea> </div> </section> + <!-- Emergency contact section --> <section class="cv-section"> <h3>EMERGENCY CONTACT</h3> <div class="form-group"> @@ -221,6 +275,7 @@ Onboard New Employee </div> {% endif %} </div> + <!-- Emergency contact phone input and error handling --> <div class="form-group"> {{ form.emergency_contact_phone.label_tag }} {{ form.emergency_contact_phone }} @@ -234,6 +289,7 @@ Onboard New Employee </div> </section> + <!-- ID information section --> <section class="cv-section"> <h3>ID INFORMATION</h3> <div class="form-group"> @@ -247,6 +303,7 @@ Onboard New Employee </div> {% endif %} </div> + <!-- ID card front and back image upload with error handling --> <div class="form-group"> {{ form.id_card_front.label_tag }} {{ form.id_card_front }} @@ -271,6 +328,7 @@ Onboard New Employee </div> </section> + <!-- Documents section (e.g., CV and police report) --> <section class="cv-section"> <h3>DOCUMENTS</h3> <div class="form-group"> @@ -297,6 +355,7 @@ Onboard New Employee </div> </section> + <!-- Privacy options section --> <section class="cv-section"> <h3>PRIVACY OPTIONS</h3> <div class="form-group"> @@ -308,10 +367,12 @@ Onboard New Employee </div> </section> + <!-- Submit button for the entire form --> <button type="submit" class="btn btn-primary">Submit</button> </form> </div> +<!-- Script to handle profile picture upload preview --> <script> document.getElementById('profile-upload').addEventListener('change', function(event) { const file = event.target.files[0]; diff --git a/postgresTest/PROJECT1/templates/request_consent.html b/postgresTest/PROJECT1/templates/request_consent.html index a3ac977e..d2053e58 100644 --- a/postgresTest/PROJECT1/templates/request_consent.html +++ b/postgresTest/PROJECT1/templates/request_consent.html @@ -1,31 +1,51 @@ {% extends 'base.html' %} +<!-- This template extends the 'base.html' layout, inheriting all its structure and design --> + {% block title %}Request Consent{% endblock title %} +<!-- The title block is overridden here with the title "Request Consent" to set the page title --> {% block content %} +<!-- Main content block begins, where the specific page content is injected --> + <h1>Request Consent to View Information</h1> +<!-- Header for the page --> <div class="container"> + <!-- Main container for the content, typically used for Bootstrap layout to create padding and structure --> + <p>You are requesting consent to view the personal information of {{ employee.first_name }} {{ employee.last_name }}.</p> - - <!-- Display employee details --> + <!-- Informational text explaining what action is being taken, with dynamic placeholders for the employee's name --> + + <!-- Display employee details like name and job title --> <p><strong>Employee Name:</strong> {{ employee.first_name }} {{ employee.last_name }}</p> + <!-- Display the employee's first and last name dynamically from the context --> + <p><strong>Position:</strong> {{ employee.job_title }}</p> + <!-- Display the employee's job title dynamically from the context --> - <!-- Send consent request form --> + <!-- Form for sending the consent request --> <form method="POST"> {% csrf_token %} + <!-- CSRF token for protection against cross-site request forgery attacks --> + <div class="form-group"> + <!-- Form group for the submit button --> <button type="submit" class="btn btn-primary">Send Consent Request</button> + <!-- Submit button to send the consent request. When clicked, this will trigger a POST request --> </div> </form> - <!-- Messages --> + <!-- Display any messages (such as success or error notifications) --> {% if messages %} <div class="alert alert-info"> + <!-- If there are any messages, display them inside an alert box styled with Bootstrap's "alert-info" class --> {% for message in messages %} {{ message }} + <!-- Iterate over each message in the messages list and display it --> {% endfor %} </div> {% endif %} </div> + {% endblock content %} +<!-- End of the content block where the main content of the page is injected --> diff --git a/postgresTest/PROJECT1/templates/settings.html b/postgresTest/PROJECT1/templates/settings.html index 566a4828..070aeb31 100644 --- a/postgresTest/PROJECT1/templates/settings.html +++ b/postgresTest/PROJECT1/templates/settings.html @@ -8,24 +8,27 @@ <!-- Privacy Settings Section --> {% if request.user.role == 'EMPLOYEE' %} - <h4>Privacy Settings</h4> - <form method="POST" action="{% url 'update_privacy' %}"> - {% csrf_token %} - <div class="form-group form-check"> - {{ form.allow_public_access }} - <label class="form-check-label" for="allow_public_access">Allow public access to my profile</label> - </div> + <h4>Privacy Settings</h4> + <form method="POST" action="{% url 'update_privacy' %}"> + {% csrf_token %} + <div class="form-group form-check"> + {{ form.allow_public_access }} + <label class="form-check-label" for="allow_public_access">Allow public access to my profile</label> + </div> - <div class="form-group form-check"> - {{ form.consent_given }} - <label class="form-check-label" for="consent_given">Consent for companies to access my profile</label> - </div> + <div class="form-group form-check"> + {{ form.consent_given }} + <label class="form-check-label" for="consent_given">Consent for companies to access my profile</label> + </div> + + <button type="submit" class="btn btn-primary">Update Privacy Settings</button> + </form> +{% elif request.user.role == 'COMPANY' %} + <p>Company accounts do not have privacy settings.</p> +{% else %} + <p>You do not have any privacy settings to configure.</p> +{% endif %} - <button type="submit" class="btn btn-primary">Update Privacy Settings</button> - </form> - {% elif request.user.role == 'COMPANY' %} - <p>Company accounts do not have privacy settings.</p> - {% endif %} <hr> <!-- Language Translation Section --> diff --git a/postgresTest/PROJECT1/urls.py b/postgresTest/PROJECT1/urls.py index 1c0790db..f6374bf7 100644 --- a/postgresTest/PROJECT1/urls.py +++ b/postgresTest/PROJECT1/urls.py @@ -1,42 +1,59 @@ -from django.urls import path, include -from . import views -from django.conf import settings -from django.conf.urls.static import static -from .views import delete_account, CustomLoginView, profile_view, profile_edit_view, edit_role -from django.contrib.auth import views as auth_views +from django.urls import path, include # Import path and include for URL routing +from . import views # Import views from the current directory +from django.conf import settings # Import settings for handling media/static files +from django.conf.urls.static import static # Import static to serve media files in development +from .views import delete_account, CustomLoginView, profile_view, profile_edit_view, edit_role # Import specific views for use in URL patterns +from django.contrib.auth import views as auth_views # Alias Django's default auth views urlpatterns = [ - path('', views.home, name='home'), - path('custom_login/', views.custom_login, name='custom_login'), - path('register/', views.register, name='register'), - path('delete_account/', delete_account, name='delete_account'), - path('login/', CustomLoginView.as_view(), name='login'), - path('logout/', views.logout_view, name='logout'), - path('accounts/profile/', profile_view, name='profile'), - path('accounts/profile/edit/', profile_edit_view, name='profile_edit'), - path('accounts/', include('allauth.urls')), - - # Employee-related paths - path('employees/', views.employee_list, name='employee_list'), # Plural for list - path('employee/<int:employee_id>/', views.view_employee_details, name='view_employee_details'), # Singular for details - - # Role management - path('edit-role/<int:user_id>/', edit_role, name='edit_role'), - - # Onboarding-related paths - path('onboard/', views.onboard_employee, name='onboard_employee'), - path('onboarding-success/<int:employee_id>/', views.onboarding_success, name='onboarding_success'), - - # Company-related paths - path('onboard-company/', views.onboard_company, name='onboard_company'), - path('company-onboarding-success/<int:company_id>/', views.company_onboarding_success, name='company_onboarding_success'), - - # Consent management - path('manage-consent/', views.manage_consent_requests, name='manage_consent'), - path('request-consent/<int:employee_id>/', views.request_consent, name='request_consent'), - - # Settings and privacy - path('settings/', views.settings_view, name='settings'), - path('set_language/', views.set_language, name='set_language'), - path('update_privacy/', views.update_privacy, name='update_privacy'), -] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + # Home page + path('', views.home, name='home'), # The home page of the site, handled by 'home' view + + # Custom login view + path('custom_login/', views.custom_login, name='custom_login'), # Custom login page handled by 'custom_login' view + + # User registration + path('register/', views.register, name='register'), # User registration page handled by 'register' view + + # Account deletion + path('delete_account/', delete_account, name='delete_account'), # URL to delete user account using the 'delete_account' view + + # Custom login and logout paths + path('login/', CustomLoginView.as_view(), name='login'), # CustomLoginView used for the login page + path('logout/', views.logout_view, name='logout'), # Logout handled by 'logout_view' + + # Profile-related paths + path('accounts/profile/', profile_view, name='profile'), # User profile page handled by 'profile_view' + path('accounts/profile/edit/', profile_edit_view, name='profile_edit'), # Profile editing page handled by 'profile_edit_view' + + # Including paths from django-allauth for additional account management + path('accounts/', include('allauth.urls')), # Includes the allauth URLs for account management + + # Employee management paths + path('employees/', views.employee_list, name='employee_list'), # Displays the list of employees, handled by 'employee_list' + path('employee/<int:employee_id>/', views.view_employee_details, name='view_employee_details'), # Displays details of a single employee based on employee_id + + # Role management paths + path('edit-role/<int:user_id>/', edit_role, name='edit_role'), # URL to edit a user's role, handled by 'edit_role' view + + # Onboarding-related paths for employees + path('onboard/', views.onboard_employee, name='onboard_employee'), # Handles the onboarding process for employees + path('onboarding-success/<int:employee_id>/', views.onboarding_success, name='onboarding_success'), # Displays onboarding success for an employee + + # Company onboarding paths + path('onboard-company/', views.onboard_company, name='onboard_company'), # Handles onboarding process for companies + path('company-onboarding-success/<int:company_id>/', views.company_onboarding_success, name='company_onboarding_success'), # Displays company onboarding success + + # Consent management paths + path('manage-consent/', views.manage_consent_requests, name='manage_consent'), # Page to manage consent requests from users + path('request-consent/<int:employee_id>/', views.request_consent, name='request_consent'), # Allows requesting consent to view employee information + + # User settings and privacy paths + path('settings/', views.settings_view, name='settings'), # Handles the settings view for user preferences + path('set_language/', views.set_language, name='set_language'), # Handles changing the language for the user + path('update_privacy/', views.update_privacy, name='update_privacy'), # Updates privacy settings for users +] + +# Serve media files (like user-uploaded files) during development by appending media URL and root +# The 'static' function is only used in development mode, not in production. ++ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) -- GitLab