You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3012 lines
115 KiB

11 months ago
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/remixicon@2.5.0/fonts/remixicon.css" rel="stylesheet">
3 weeks ago
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
11 months ago
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css" integrity="sha512-z3gLpd7yknf1YoNbCzqRKc4qyor8gaKU1qmn+CShxbuBusANI9QpRohGBreCFkKxLhei6S9CQXFEbbKuqLg0DA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<style>
2 months ago
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap');
11 months ago
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Roboto', sans-serif;
}
2 months ago
11 months ago
body {
position: relative;
width: 100%;
2 months ago
height: 100vh; /* Ensure full viewport height */
overflow: hidden; /* Prevent body scrolling */
11 months ago
}
.header {
height: 60px;
width: 100%;
display: flex;
align-items: center;
border-bottom: 2px solid #F1F1F1;
2 months ago
background-color: #fff;
3 weeks ago
<!-- z-index: 1000; /* Ensure header stays on top */-->
2 months ago
position: fixed;
top: 0;
11 months ago
}
2 months ago
11 months ago
.logo {
display: flex;
align-items: center;
width: 300px;
padding-left: 40px;
}
.logo span {
color: #5073FB;
}
.search--notification--profile {
display: flex;
align-items: center;
justify-content: space-between;
width: calc(100% - 300px);
padding: 0 40px;
}
.search {
2 months ago
margin-left: 500px;
11 months ago
background-color: #F1F4F8;
border-radius: 50px;
width: 400px;
padding: 5px;
display: flex;
align-items: center;
justify-content: space-between;
}
.search input {
background-color: transparent;
outline: none;
border: none;
text-indent: 15px;
width: 85%;
}
.search button {
outline: none;
border: none;
border-radius: 50%;
background-color: #fff;
padding: 8px;
display: flex;
align-items: center;
justify-content: center;
}
.search button i {
font-size: 1.1rem;
color: #5073FB;
}
.notification--profile {
display: flex;
align-items: center;
}
.picon {
margin-left: 20px;
font-size: 1.1rem;
padding: 5px;
border-radius: 5px;
}
.lock {
color: #5073FB;
background-color: rgba(80, 115, 251, .2);
}
.bell {
color: #F1D243;
background-color: rgba(241, 210, 67, .2);
}
.chat {
color: #70D7A5;
background-color: rgba(112, 215, 165, .2);
}
.profile {
position: relative;
width: 40px;
height: 40px;
border-radius: 50%;
overflow: hidden;
}
.main {
position: relative;
width: 100%;
2 months ago
height: calc(100vh - 60px);
overflow-y: auto;
overflow-x: hidden;
11 months ago
}
.sidebar {
2 months ago
position: fixed;
top: 60px; /* Start after header */
11 months ago
left: 0;
2 months ago
height: calc(100vh - 60px); /* Full height minus header */
11 months ago
width: 300px;
background-color: #fff;
padding: 30px;
display: flex;
flex-direction: column;
justify-content: space-between;
border-right: 2px solid #F1F1F1;
2 months ago
transition: 0.3s;
z-index: 900; /* Ensure sidebar is below header */
11 months ago
}
2 months ago
11 months ago
.sidebar.active {
width: 103px;
overflow: hidden;
}
.sidebar.active .sidebar--item {
display: none;
}
li {
list-style: none;
}
a {
text-decoration: none;
}
.sidebar--items a,
.sidebar--bottom-items a {
display: flex;
align-items: center;
margin-bottom: 10px;
font-size: 1.1rem;
color: #000;
padding: 10px;
2 weeks ago
border-radius: 50px;
11 months ago
}
.sidebar--items a:hover,
.sidebar--bottom-items a:hover {
background-color: #5073FB;
color: #fff;
}
#active--link {
background-color: #5073FB;
color: #fff;
}
.sidebar--bottom-items li:last-child a {
margin-bottom: 0;
}
.icon {
position: relative;
display: flex;
align-items: center;
justify-content: center;
margin-right: 20px;
font-size: 1.3rem;
}
.icon-0 {
color: #5073FB;
}
.icon-1 {
color: #C5BC58;
}
.icon-2 {
color: #A280E9;
}
.icon-3 {
color: #85ADE3;
}
.icon-4 {
color: #E36AC8;
}
.icon-5 {
color: #70D7A5;
}
.icon-6 {
color: #5F5CE0;
}
.icon-7 {
color: #E86786;
}
.icon-8 {
color: #F1D243;
}
2 months ago
.main::-webkit-scrollbar, .sidebar::-webkit-scrollbar {
width: 10px;
}
.main::-webkit-scrollbar-track, .sidebar::-webkit-scrollbar-track {
background: #f1f1f1;
}
.main::-webkit-scrollbar-thumb, .sidebar::-webkit-scrollbar-thumb {
background: #888;
}
.main::-webkit-scrollbar-thumb:hover, .sidebar::-webkit-scrollbar-thumb:hover {
background: #555;
}
2 weeks ago
.sidebar-link.active {
background-color: #007bff;
color: white !important;
border-radius: 5px;
font-weight: bold;
}
2 months ago
11 months ago
</style>
<title>Dashboard</title>
</head>
<body>
<section class="header">
<div class="logo">
<i class="ri-menu-line icon icon-0 menu"></i>
2 months ago
<h2><nobr>{{ first_name }} Dashboard</nobr></h2>
11 months ago
</div>
<div class="search--notification--profile">
<div class="search">
<input type="text" placeholder="Search">
<button><i class="ri-search-2-line"></i></button>
</div>
<div class="notification--profile">
<div class="picon bell">
<i class="ri-notification-2-line"></i>
</div>
<div class="picon chat">
<i class="ri-wechat-2-line"></i>
</div>
</div>
</div>
</section>
<section class="main">
<div class="sidebar">
<ul class="sidebar--items">
2 weeks ago
<li>
<a href="#" id="newJobPosting" class="sidebar-link" onclick="activateSidebarLink(this); loadUserPage('/new_job_posting/', '{{ user_id }}');">
<span class="icon icon-3"><i class="far fa-calendar-alt"></i></span>
<span class="sidebar--item" style="white-space: nowrap;">New Jobs Postings</span>
</a>
</li>
<li>
<a href="#" id="allJobPosting" class="sidebar-link" onclick="activateSidebarLink(this); loadUserPage('/all_job_postings/', '{{ user_id }}');">
<span class="icon icon-2"><i class="far fa-calendar-alt"></i></span>
<span class="sidebar--item">All Jobs Postings</span>
</a>
</li>
<li>
<a href="#" id="Messages" class="sidebar-link" onclick="activateSidebarLink(this); loadUserPage('/messages/', '{{ user_id }}');">
<span id="messageNotificationBadge" style="position: absolute;right: 100px; background-color: red;color: white;font-size: 12px;font-weight: bold;border-radius: 50%; padding: 5px 8px;width: auto;height: auto;text-align: center;display: none;"></span>
<span class="icon icon-4"><i class="fas fa-envelope"></i></span>
<span class="sidebar--item">Messages</span>
</a>
</li>
<li>
<a href="#" class="sidebar-link" >
<span class="icon icon-4"><i class="fa-regular fa-clock"></i></span>
<span class="sidebar--item">Pending Process</span>
</a>
</li>
<li>
<a href="#" class="sidebar-link" >
<span class="icon icon-5"><i class="fa fa-paper-plane"></i></span>
<span class="sidebar--item">Submitted Resumes</span>
</a>
</li>
<li>
<a href="#" class="sidebar-link" >
<span class="icon icon-6"><i class="fa-solid fa-person"></i></span>
<span class="sidebar--item">Client Details</span>
</a>
</li>
<li>
<a href="#" class="sidebar-link" >
<span class="icon icon-6"><i class="fas fa-chart-bar"></i></span>
<span class="sidebar--item">Activity Report</span>
</a>
</li>
11 months ago
</ul>
<ul class="sidebar--bottom-items">
<li>
<a href="#">
<span class="icon icon-7"><i class="fas fa-cog"></i></span>
<span class="sidebar--item">Settings</span>
</a>
</li>
<li>
<a href="{% url 'logout' %}">
<span class="icon icon-8"><i class="fas fa-sign-out-alt"></i></span>
<span class="sidebar--item">Logout</span>
</a>
</li>
2 months ago
11 months ago
</ul>
</div>
2 months ago
<div id="dynamicContentContainer">
2 weeks ago
<input type="hidden" id="user_id" name="user_id" value="{{ user_id }}">
2 months ago
</div>
3 weeks ago
2 months ago
<!-- <div id="hyperlinkContainer" style="display: none;">-->
<!-- <div class="hyperlink-content" id="customModal" style="background-color: red;margin-top: -500px; width: 400px; margin-left: 700px;">-->
<!-- <h5>Access Restricted</h5>-->
<!-- <p>You are assigned a band level below 5. You cannot access the job posting page.</p>-->
<!-- </div>-->
<!-- </div>-->
3 weeks ago
<div id="content">
<!-- Page content will be loaded here -->
</div>
11 months ago
</section>
2 months ago
<script>
2 weeks ago
function activateSidebarLink(selectedLink) {
// Remove 'active' from all sidebar links
document.querySelectorAll('.sidebar-link').forEach(link => {
link.classList.remove('active');
});
// Add 'active' class to clicked link
selectedLink.classList.add('active');
}
2 months ago
3 weeks ago
// messages //
3 weeks ago
document.addEventListener('DOMContentLoaded', function() {
2 weeks ago
const userId = document.getElementById('user_id').value;
function updateMessageNotification() {
fetch(`/unread_message_count/?user_id=${userId}`)
.then(response => response.json())
3 weeks ago
.then(data => {
2 weeks ago
console.log(data.unread_count);
const notificationBadge = document.getElementById('messageNotificationBadge');
if (data.unread_count > 0) {
notificationBadge.textContent = data.unread_count ;
notificationBadge.style.display = 'inline-flex'; // Show badge if there are unread messages
} else {
notificationBadge.style.display = 'none'; // Hide badge if no unread messages
}
3 weeks ago
})
2 weeks ago
.catch(error => console.error('Error fetching unread message count:', error));
}
updateMessageNotification();
3 weeks ago
})
2 weeks ago
3 weeks ago
function findMainMessageId(message_id) {
console.log(message_id);
const userId = document.getElementById('user_id').value;
return fetch(`/get_main_message_id/${encodeURIComponent(message_id)}/?user_id=${encodeURIComponent(userId)}`)
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return response.json();
})
.then(data => {
console.log("Main Message ID:", data.main_message_id);
return data.main_message_id;
})
.catch(error => {
console.error('Error fetching main message ID:', error);
return null;
});
}
function toggleMessageStatus(event, message_id, parent_message_id) {
event.preventDefault();
const statusContainer = document.getElementById(`statusContainer_${message_id}`);
const isCurrentlyVisible = statusContainer.style.display === 'block';
// Toggle visibility
statusContainer.style.display = isCurrentlyVisible ? 'none' : 'block';
if (!isCurrentlyVisible) {
// Fetch the message status if it's being shown
fetchMessageStatus(message_id, parent_message_id);
}
}
function fetchMessageStatus(message_id, parent_message_id) {
const userId = document.getElementById('user_id').value;
// Make the fetch call to get message status
fetch(`/get_message_status/${message_id}/?user_id=${userId}`)
.then(response => response.json())
.then(data => {
let statusContainer = document.getElementById(`statusContainer_${message_id}`);
statusContainer.innerHTML = ""; // Clear previous content
// Populate status container with the fetched data
data.status.forEach(item => {
let p = document.createElement("p");
p.textContent = `${item.email} - ${item.seen_time}`;
statusContainer.appendChild(p);
});
statusContainer.style.display='block';
setTimeout(() => {
statusContainer.style.opacity = 1;
}, 50);
})
.catch(error => {
console.error('Error fetching message status:', error);
});
}
function toggleMoreInfo(message_id, type) {
// Toggle the visibility of the 'more-info' container
const moreInfoContainer = document.getElementById(`more-info-${message_id}`);
const isCurrentlyVisible = moreInfoContainer.style.display === 'block';
// Set the display property based on current visibility
moreInfoContainer.style.display = isCurrentlyVisible ? 'none' : 'block';
// Only fetch timestamps if the info section is being displayed
if (!isCurrentlyVisible) {
// Call the function to fetch timestamps
fetchDownloadTimestamps(message_id, type);
}
}
function trackDownload(message_id) {
const userId = document.getElementById('user_id').value;
console.log(message_id);
// Fetch download details for all recipients of the message
fetch(`/track_download/${message_id}/?user_id=${userId}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(data => {
console.log(data);
const timestampsContainer = document.getElementById('download-timestamps-list');
// Update HTML to show download timestamps for each recipient
timestampsContainer.innerHTML = `
${Object.entries(data.downloads || {}).map(([recipient, timestamps]) => `
<div>
${timestamps.first_downloaded
? `<span>First Downloaded: ${new Date(timestamps.first_downloaded).toLocaleString()}</span><br>`
: ''
}
${timestamps.last_downloaded
? `<span>Last Downloaded: ${new Date(timestamps.last_downloaded).toLocaleString()}</span>`
: ''
}
</div>
`).join('')}
`;
timestampsContainer.style.display ='none';
})
.catch(error => {
console.error('Error tracking download:', error);
});
}
function showMessageDetails(message_id) {
console.log(message_id);
const MessagesData = window.MessagesDetails;
console.log(MessagesData);
const MessagesDataIndex = MessagesData.find(message =>
Array.isArray(message.replies) && message.replies.some(reply => reply.message_id === message_id)
) || MessagesData.find(msg => msg.latest_message.message_id === message_id);
console.log(MessagesDataIndex);
const parentMessageId = MessagesDataIndex.message_id
<!-- const MessagesDataIndex = parentMsg[parentMessageId]-->
<!-- console.log(MessagesDataIndex);-->
const messageDetailsContainer = document.getElementById('MessageDetailsContainer');
const messageDetails = document.getElementById('MessageDetails');
const inboxContainer = document.getElementById('InboxContainer');
const thread = document.getElementById('ConversationThread');
console.log(MessagesDataIndex.message_id)
const userId = document.getElementById('user_id').value;
const current_user_id = document.getElementById('current_user_id').value;
const attachmentHtml = (MessagesDataIndex.attachment && MessagesDataIndex.attachment.length > 0)
? MessagesDataIndex.attachment.map(attachment => `
<div class="attachment-container" style="display: flex; align-items: center; gap: 12px; margin-top: 20px; border: 1px solid #ddd; padding: 15px; border-radius: 8px; background-color: #f7f7f7; max-width: 40%;">
<div style="flex-shrink: 0;">
<span class="material-icons" style="font-size: 36px; color: #555;">insert_drive_file</span>
</div>
<div style="flex-grow: 1; min-width: 0;">
<div style="font-weight: bold; font-size: 14px; color: #222; word-wrap: break-word; overflow: hidden; text-overflow: ellipsis;">
${attachment.filename}
</div>
</div>
<a href="${attachment.url}" download="${attachment.filename}"
onclick="trackDownload('${MessagesDataIndex.message_id}')"
style="padding: 8px 12px; background-color: #28a745; color: white; text-decoration: none; border-radius: 4px; font-size: 12px; cursor: pointer;">
Download
</a>
<div style="position: relative;">
<button type="button" class="material-icons" onclick="toggleMoreInfo('${MessagesDataIndex.message_id}', 'main')"
style="font-size: 24px; border: none; background: none; cursor: pointer; color: #007BFF;">
info
</button>
<div id="more-info-${MessagesDataIndex.message_id}" style="display: none; position: absolute; top: 0; left: calc(100% + 10px); width: 300px;height: auto;
padding: 10px; border-radius: 8px; background-color: #fff;box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); font-size: 13px; color: #444;overflow-y: hidden;">
<div><strong>File Size:</strong> ${(attachment.size / 1024).toFixed(2)} KB</div>
<div><strong>Recipients:</strong> ${MessagesDataIndex.recipient_emails.join(', ')}</div>
<div id="download-timestamps-section">
<div id="download-timestamps-list-${MessagesDataIndex.message_id}"></div>
</div>
</div>
</div>
</div>
`).join('')
: '<p style="margin-top: 20px; color: #555;"></p>';
messageDetails.innerHTML = `
${MessagesDataIndex.sender_id === current_user_id ?
`
<h3 style= "margin-left:1px;"><strong></strong>${MessagesDataIndex.subject}</h3>`
:`<h3><strong></strong>${MessagesDataIndex.subject}</h3>`}<br>
<p><strong>From:</strong> ${MessagesDataIndex.sender_id}</p><br>
<p><strong>To:</strong> ${MessagesDataIndex.recipient_emails}</p><br>
<div style="position:relative;">
<i class="fa-solid fa-circle-info info-icon" id="fetchStatusBtn"
data-message-id="${MessagesDataIndex.message_id}" onclick="toggleMessageStatus(event,'${parentMessageId}')"
style="color: blue; margin-left:390px; cursor: pointer; font-size: 18px;">
</i>
<div id="statusContainer_${MessagesDataIndex.message_id}"
style="display: none; position: absolute; top: -10px; left: 420px; width: 300px; padding: 10px;
border-radius: 8px; background-color: #f9f9f9; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); font-size: 14px;
color: #444; height: auto; overflow-y: hidden; transition: opacity 0.3s ease-in-out; opacity: 0;">
</div>
</div>
<p style= "margin-top:-20px;"><strong>Sent Time:</strong> ${new Date(MessagesDataIndex.sent_at).toLocaleString()}</p>
<h4 style="margin-left:300px; margin-top:-20px;" >More Info</h4>
<p style="margin-top: 20px; margin-bottom:20px; padding-bottom: 15px; ">${MessagesDataIndex.body}</p>
${MessagesDataIndex.attachment.length > 0 ? `<p style="border-top: 1px solid #D3D3D3;padding: 10px;"><b>Attachment File:</b>
${attachmentHtml}<p>`: ''}
<div id="download-timestamps-list" style="font-size: 12px; color: #555; margin-top: 10px;"></div>
<div class= "replyWrapper" style="margin-top: 20px;">
<button id="replyButton" onclick="replyMessage(event, '${parentMessageId}', 'reply')" style="margin-top: 10px; padding: 5px 10px; background-color: #007BFF; color: white; border: none; border-radius: 4px; cursor: pointer;">Reply</button>
${MessagesDataIndex.recipient_emails.length > 1 ? `
<button type="button" data-reply='${JSON.stringify(MessagesDataIndex)}' id="replyAllButton" onclick="replyMessage(event, '${parentMessageId}', 'replyAll')" style="margin-top: 10px; padding: 5px 10px; background-color: #007BFF; color: white; border: none; border-radius: 4px; cursor: pointer;">
Reply All</button>`: ''}
</div>
<div id="replies_${MessagesDataIndex.message_id}" class="RepliesContainer" style="margin-top: 20px;"></div>
`;
// Show message details and hide the inbox
inboxContainer.style.display = 'none';
messageDetailsContainer.style.display = 'block';
thread.style.display = 'block';
fetch(`/update_message_read_status/${message_id}/?user_id=${userId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': '{{ csrf_token }}' // If using CSRF protection
},
})
.then(response => response.json())
.then(data => {
console.log('Message marked as read:', data);
updateMessageReadStatus(message_id)
})
.catch(error => {
console.error('Error marking message as read:', error);
});
2 weeks ago
function updateMessageReadStatus(message_id) {
3 weeks ago
const messageRow = document.querySelector(`[data-message-id="${message_id}"]`);
2 weeks ago
if (messageRow) {
// Update background color for read messages
messageRow.style.backgroundColor = '#efeded';
// Remove bold styling from sender, subject, and timestamp
const sender = messageRow.querySelector('.emailRow__title');
const subject = messageRow.querySelector('.emailRow__message h4');
const timestamp = messageRow.querySelector('.emailRow__time');
if (sender) sender.style.fontWeight = 'normal';
if (subject) subject.style.fontWeight = 'normal';
if (timestamp) timestamp.style.fontWeight = 'normal';
}
}
fetch(`/unread_message_count/?user_id=${userId}`)
.then(response => response.json())
.then(data => {
2 weeks ago
console.log('unread_count:',data.unread_count);
2 weeks ago
const notificationBadge = document.getElementById('messageNotificationBadge');
if (data.unread_count > 0) {
notificationBadge.textContent = data.unread_count ;
notificationBadge.style.display = 'inline-flex'; // Show badge if there are unread messages
} else {
notificationBadge.style.display = 'none'; // Hide badge if no unread messages
}
})
.catch(error => console.error('Error fetching unread message count:', error));
3 weeks ago
const repliesContainer = document.getElementById(`replies_${parentMessageId}`);
console.log(repliesContainer);
repliesContainer.innerHTML = ''; // Clear existing replies
console.log(parentMessageId);
fetch(`/fetch_replies/${parentMessageId}/?user_id=${userId}`)
.then(response => response.json())
.then(data => {
console.log("Replies fetched:", data);
renderReplies(data.replies, repliesContainer);
})
.catch(error => {
console.error('Error fetching replies:', error);
});
<!-- console.log(messageId);-->
<!-- fetch(`/fetch_download_timestamps/${messageId}/?user_id=${userId}`)-->
<!-- .then(response => response.json())-->
<!-- .then(data => {-->
<!-- console.log('Download timestamps:', data);-->
<!-- const timestampsListContainer = document.getElementById('download-timestamps-list');-->
<!-- const downloadTimestampsSection = document.getElementById('download-timestamps-section');-->
<!-- let downloadTimestampsHtml = '';-->
<!-- // Check if the current user is the sender-->
<!-- if (MessagesDataIndex.sender_id === data.current_user_id) {-->
<!-- console.log('Current User ID:', data.current_user_id);-->
<!-- // Display main message download timestamps-->
<!-- downloadTimestampsHtml += `<h3>Main Message Downloads</h3>`;-->
<!-- data.main_message_downloads.forEach(record => {-->
<!-- downloadTimestampsHtml += `-->
<!-- <p><strong>Recipient:</strong> ${record.recipient_id}</p>-->
<!-- <p>First Downloaded: ${record.first_downloaded || 'Not downloaded yet'}</p>-->
<!-- <p>Last Downloaded: ${record.last_downloaded || 'Not downloaded yet'}</p>-->
<!-- <hr/>-->
<!-- `;-->
<!-- });-->
<!-- // Display reply messages download timestamps-->
<!-- Object.keys(data.reply_message_downloads).forEach(replyId => {-->
<!-- downloadTimestampsHtml += `<h3>Reply Message ID: ${replyId}</h3>`;-->
<!-- data.reply_message_downloads[replyId].forEach(record => {-->
<!-- downloadTimestampsHtml += `-->
<!-- <p><strong>Recipient:</strong> ${record.recipient_id}</p>-->
<!-- <p>First Downloaded: ${record.first_downloaded || 'Not downloaded yet'}</p>-->
<!-- <p>Last Downloaded: ${record.last_downloaded || 'Not downloaded yet'}</p>-->
<!-- <hr/>-->
<!-- `;-->
<!-- });-->
<!-- });-->
<!-- // Update the UI-->
<!-- if (downloadTimestampsHtml.trim() !== '') {-->
<!-- timestampsListContainer.innerHTML = downloadTimestampsHtml;-->
<!-- timestampsListContainer.style.display = 'block';-->
<!-- downloadTimestampsSection.style.display = 'block';-->
<!-- } else {-->
<!-- timestampsListContainer.innerHTML = '';-->
<!-- timestampsListContainer.style.display = 'none';-->
<!-- downloadTimestampsSection.style.display = 'none';-->
<!-- }-->
<!-- }-->
<!-- })-->
<!-- .catch(error => {-->
<!-- console.error('Error fetching download timestamps:', error);-->
<!-- });-->
}
function fetchDownloadTimestamps(message_id, type) {
const userId = document.getElementById('user_id').value;
console.log(`fetchDownloadTimestamps: ${message_id}`);
fetch(`/fetch_download_timestamps/${message_id}/?user_id=${userId}`)
.then(response => response.json())
.then(data => {
console.log(data);
const timestampsListContainer = document.getElementById(`download-timestamps-list-${message_id}`);
const current_user_id = document.getElementById('current_user_id').value;
const senderId = data.main_message_downloads[0]?.sender_id;
let downloadTimestampsHtml = '';
if (type === 'main') {
console.log(current_user_id);
if(senderId === current_user_id) {
data.main_message_downloads.forEach((record,index) => {
downloadTimestampsHtml += `
<p><strong>${record.recipient_id}</strong></p>
<b>First Downloaded:</b> ${record.first_downloaded || 'Not downloaded yet'}
<b>Last Downloaded: </b>${record.last_downloaded || 'Not downloaded yet'}
`;
if (index < data.main_message_downloads.length-1) {
downloadTimestampsHtml +=`<hr>`
}
});
}
else{
console.log('User is not the sender, not displaying timestamps.');
document.getElementById('download-timestamps-section').style.display = 'none';
}
} else if (type === 'reply') {
console.log(data.main_message_downloads);
if(senderId === current_user_id) {
data.main_message_downloads.forEach((record,index) => {
downloadTimestampsHtml += `
<p><strong>${record.recipient_id}</strong></p>
<p>First Downloaded: ${record.first_downloaded || 'Not downloaded yet'}</p>
<p>Last Downloaded: ${record.last_downloaded || 'Not downloaded yet'}</p>
`;
<!-- if (index < data.main_message_downloads.length-1) {-->
<!-- downloadTimestampsHtml +=`<hr>`-->
<!-- }-->
});
}
else{
console.log('User is not the sender, not displaying timestamps.');
document.getElementById('download-timestamps-section').style.display = 'none';
}
}
timestampsListContainer.innerHTML = downloadTimestampsHtml;
timestampsListContainer.style.display = downloadTimestampsHtml.trim() ? 'block' : 'none';
})
.catch(error => {
console.error('Error fetching download timestamps:', error);
});
}
function HideMessageDetails() {
const messageDetailsContainer = document.getElementById('MessageDetailsContainer');
const inboxContainer = document.getElementById('InboxContainer');
inboxContainer.style.display = 'block';
messageDetailsContainer.style.display = 'none';
}
function backToInbox(event) {
event.preventDefault();
const inboxContainer = document.getElementById('InboxContainer');
const messageDetailsContainer = document.getElementById('MessageDetailsContainer');
// Show inbox and hide message details
inboxContainer.style.display = 'block';
messageDetailsContainer.style.display = 'none';
}
function replyMessage(event, message_id, type) {
event.preventDefault();
console.log(message_id);
const button = event.currentTarget; // Get the button that triggered the event
const attribute = button.getAttribute('data-reply');
const dataReply = JSON.parse(attribute);
console.log(dataReply);
const MessagesData = window.MessagesDetails;
console.log(MessagesData);
const main_message_id = findMainMessageId(message_id).then(mainMessageId => {
console.log(mainMessageId);
});
const message = dataReply || MessagesData.find(message =>
Array.isArray(message.replies) && message.replies.some(reply => reply.message_id === message_id)
) || MessagesData.find(msg => msg.latest_message.message_id === message_id) || MessagesData.find(msg => msg.message_id === message_id)
console.log("Message Object:", message);
// Remove any existing thread containers
const existingThreadContainer = document.querySelector('.ThreadContainer');
if (existingThreadContainer) {
existingThreadContainer.remove();
}
// Create a container to wrap both button and thread
const wrapper = button.closest('.replyWrapper'); // Ensure the button is wrapped in a parent container
if (!wrapper) {
console.error("Button must be inside a wrapper with class 'replyWrapper'.");
return;
}
// Check for and remove any existing thread containers within the wrapper
const threadContainer = wrapper.querySelector('.ThreadContainer');
if (threadContainer) threadContainer.remove();
// Create a new thread container
const newThreadContainer = document.createElement('div');
newThreadContainer.className = 'ThreadContainer';
newThreadContainer.style.border = 'none';
newThreadContainer.style.marginTop = '20px'; // Adjusted gap
newThreadContainer.style.padding = '10px';
let recipients = '';
if (type === 'reply') {
recipients = message.sender_id;
} else if (type === 'replyAll') {
const current_user_id = document.getElementById('current_user_id').value;
console.log(current_user_id);
// Combine recipient emails and IDs, filter out the current user
const recipientEmails = [
...(message.recipient_emails || []),
...(message.recipient_id || []),
].filter(email => email !== current_user_id);
console.log("Filtered Recipient Emails/IDs:", recipientEmails);
// Include sender only if they are not the current user
recipients = recipientEmails.includes(message.sender_id) || message.sender_id === current_user_id
? recipientEmails.join(', ')
: `${message.sender_id}, ${recipientEmails.join(', ')}`;
}
// Construct dynamic email bar for each recipient
let emailBarsHtml = '';
const emailList = recipients.split(',')
.map(email => email.trim())
.filter(email => email && email !== current_user_id); // Remove empty strings and current user
console.log(emailList);
emailList.forEach((email, index) => {
const emailLength = email.length; // Get the length of the email
emailBarsHtml += `
<input class="email-bar" type="text" value='${email}'
style="font-size: 14px; font-weight: 500; color: #333; border: none; outline: none; width: auto;"
size="${emailLength}" readonly/>`;
if (index < emailList.length - 1) {
emailBarsHtml += `,`;
}
});
// Populate the thread container with form content
newThreadContainer.innerHTML = `
<form id="ComposeMessage" method="post"action="{% url 'send_reply' %}?user_id={{ user_id }}">
<div id="ComposeBox" style="padding: 20px; width:55%; height:250px; box-sizing:border-box; margin-top: 20px; border:none; box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.3);">
<!-- Close Button -->
<button type="button" id="closeComposeBtn"
style="position:absolute; margin-top:-5px; left: 630px; background: red; color: white; border: none; border-radius: 50%; width: 25px; height: 25px; cursor: pointer; font-size: 16px; display: flex; align-items: center; justify-content: center;">
&times;
</button>
<div id="emailBars">${emailBarsHtml}</div> <!-- Dynamic email bars -->
2 weeks ago
<textarea id="message" name="message" placeholder="" style="width: 107%; height: 150px; border: none; margin-bottom: 10px; margin-left: -20px; border-top:1px solid #D3D3D3; outline: none; padding: 5px; resize: none; box-sizing: border-box;"></textarea>
3 weeks ago
<button type="button" style="border-radius: 10px; top:-800px; color:white; background:#1F51FF;font-size:17px; border: none; width:70px; height:30px; font-weight:bold;" onclick="sendReply(event, '${message.message_id}')">Send</button>
2 weeks ago
<i class="fa-solid fa-paperclip" onclick="document.getElementById('attachment-reply').click();" style="color:#1F51FF; margin-left:10px; font-size:23px; cursor: pointer;"></i>
<input type="file" id="attachment-reply" name="attachment" accept=".pdf,.doc,.docx,.txt" style="display: none;" onchange="showReplyFileName()">
<span id="file-name-reply" style="font-size: 14px; color: black; margin-left: 10px;"></span>
3 weeks ago
</div>
</form>
`;
wrapper.appendChild(newThreadContainer);
document.getElementById("closeComposeBtn").addEventListener("click", function() {
newThreadContainer.remove(); // Removes the compose box
});
document.addEventListener('click', function(event) {
if (!newThreadContainer.contains(event.target) && !button.contains(event.target)) {
newThreadContainer.remove();
}
});
const element = newThreadContainer.querySelector('#message');
console.log(element);
if (element) { element.focus();}
}
2 weeks ago
function showReplyFileName() {
var input = document.getElementById("attachment-reply");
var fileNameDisplay = document.getElementById("file-name-reply");
if (input.files.length > 0) {
var fullFileName = input.files[0].name;
var maxLength = 40; // Maximum characters before truncating
if (fullFileName.length > maxLength) {
var truncatedFileName = fullFileName.substring(0, maxLength) + "...";
fileNameDisplay.textContent = truncatedFileName;
} else {
fileNameDisplay.textContent = fullFileName;
}
} else {
fileNameDisplay.textContent = ""; // Clear if no file is selected
}
}
3 weeks ago
function renderReplies(replies, container) {
console.log(replies);
const current_user_id = document.getElementById('current_user_id').value;
replies.forEach(reply => {
const replyContainer = document.createElement('div');
replyContainer.classList.add('reply');
replyContainer.style.borderTop = '1px solid #ddd';
replyContainer.style.padding = '15px';
replyContainer.style.margin = '10px 0';
replyContainer.style.borderRadius = '8px';
<!-- replyContainer.style.backgroundColor = '#f9f9f9';-->
replyContainer.innerHTML ='';
const attachmentHtml = reply.attachment
?
`<div class="attachment-container" style="display: flex; align-items: center; gap: 12px; margin-top: 20px; border: 1px solid #ddd; padding: 15px; border-radius: 8px; background-color: #f7f7f7; max-width: 40%;">
<div style="flex-shrink: 0;">
<span class="material-icons" style="font-size: 36px; color: #555;">insert_drive_file</span>
</div>
<div style="flex-grow: 1; min-width: 0;">
<div style="font-weight: bold; font-size: 14px; color: #222; word-wrap: break-word; overflow: hidden; text-overflow: ellipsis;">
${reply.attachment.filename}
</div>
</div>
<a href="${reply.attachment.url}" download="${reply.attachment.name}"
onclick="trackDownload('${reply.message_id}')"
style="padding: 8px 12px; background-color: #28a745; color: white; text-decoration: none; border-radius: 4px; font-size: 12px; cursor: pointer;">
Download
</a>
<div style="position: relative;">
<button type="button" class="material-icons" onclick="toggleMoreInfo('${reply.message_id}', 'reply')"
style="font-size: 24px; border: none; background: none; cursor: pointer; color: #007BFF;">
info</button>
<div id="more-info-${reply.message_id}" style="display: none; position: absolute; top: 0; left: calc(100% + 10px); width: 300px; height: auto; padding: 10px; border: 1px solid #ddd; border-radius: 8px; background-color: #fff; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); font-size: 13px; color: #444; overflow-y: hidden;">
<div><strong>File Size:</strong> ${(reply.attachment.size / 1024).toFixed(2)} KB</div>
<div><strong>Recipients:</strong> ${reply.recipient_id.join(', ')}</div>
<div id="download-timestamps-section">
<div id="download-timestamps-list-${reply.message_id}"></div>
</div>
</div>
</div>
</div> `
: '';
const replyHTML =
`
${reply.sender_id === current_user_id ?
` <h3 style= "margin-left:1px; margin-top:0px;"><strong></strong>${reply.subject}</h3>`
:`<h3><strong></strong>${reply.subject}</h3>`}<br>
<p style=" margin-top:-20px;"><strong>From:</strong> ${reply.sender_id}</p><br>
<p><strong>To:</strong> ${reply.recipient_id.join(', ')}</p><br>
<p><strong>Sent Time:</strong> ${new Date(reply.sent_at).toLocaleString()}</p><br>
<div style="position:relative; margin-top:-60px;">
<i class="fa-solid fa-circle-info info-icon" id="fetchStatusBtn"
data-message-id="${reply.message_id}" onclick="toggleMessageStatus(event,'${reply.message_id}')"
style="color: blue; margin-left:390px; margin-top:20px; cursor: pointer; font-size: 18px;">
</i>
<div id="statusContainer_${reply.message_id}"
style="display: none; position: absolute; top: 4px; left: 420px; width: 300px; padding: 10px;
border-radius: 8px; background-color: #f9f9f9; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); font-size: 14px;
color: #444; height: auto; overflow-y: hidden; transition: opacity 0.3s ease-in-out; opacity: 0;">
</div>
</div><br>
<h4 style="margin-left:300px; margin-top:-40px;" >More Info</h4>
<p style="margin-top: 20px; margin-bottom:20px; padding-bottom: 15px;">${reply.body}</p>
${reply.attachment ? `<p style="border-top: 1px solid #D3D3D3;padding: 10px;"><b>Attachment File:</b>
${attachmentHtml}<p>`: ''}
<div class= "replyWrapper" style="margin-top: 20px;">
<button id="reply" data-reply='${JSON.stringify(reply)}' onclick="replyMessage(event, '${reply.message_id}', 'reply')" style="margin-top: 10px; padding: 5px 10px; background-color: #007BFF; color: white; border: none; border-radius: 4px; cursor: pointer;">Reply</button>
${reply.recipient_id.length > 1 ?`
<button id="replyAll" type="button" data-reply='${JSON.stringify(reply)}'
onclick="replyMessage(event, '${reply.message_id}', 'replyAll')"
style="margin-top: 10px; padding: 5px 10px; background-color: #007BFF; color: white; border: none; border-radius: 4px; cursor: pointer;">
Reply All</button>` : ''}
<button id="toggleReplies"></button>
</div>`
;
replyContainer.innerHTML = replyHTML;
container.appendChild(replyContainer);
// Add nested replies in a separate container
if (reply.replies && reply.replies.length > 0) {
const nestedRepliesContainer = document.createElement('div');
nestedRepliesContainer.classList.add('nested-replies-container');
<!-- nestedRepliesContainer.style.marginLeft = '10px';-->
<!-- nestedRepliesContainer.style.paddingLeft = '10px';-->
nestedRepliesContainer.style.display = 'none';
nestedRepliesContainer.innerHTML ='';
replyContainer.appendChild(nestedRepliesContainer);
renderReplies(reply.replies, nestedRepliesContainer);
const toggleRepliesButton = document.getElementById('toggleReplies');
2 weeks ago
<!-- console.log(toggleRepliesButton)-->
3 weeks ago
toggleRepliesButton.textContent = 'View Replies';
toggleRepliesButton.style.marginTop = '20px';
toggleRepliesButton.style.padding = '5px 10px';
toggleRepliesButton.style.backgroundColor = '#28a745';
toggleRepliesButton.style.color = 'white';
toggleRepliesButton.style.border = 'none';
toggleRepliesButton.style.borderRadius = '4px';
toggleRepliesButton.style.cursor = 'pointer';
// Toggle nested replies visibility
toggleRepliesButton.addEventListener('click', function (event) {
event.preventDefault();
if (nestedRepliesContainer.style.display === 'none') {
nestedRepliesContainer.style.display = 'block';
toggleRepliesButton.textContent = 'Hide Replies';
<!-- toggleRepliesButton.style.display = 'block';-->
} else {
nestedRepliesContainer.style.display = 'none';
toggleRepliesButton.textContent = 'View Replies';
}
});
replyContainer.appendChild(toggleRepliesButton);
}
});
}
function sendReply(event, id) {
console.log(id);
event.preventDefault();
const form = document.getElementById('ComposeReply');
const MessagesData = window.MessagesDetails;
console.log(MessagesData)
const msg = MessagesData.find(message =>
Array.isArray(message.replies) && message.replies.some(reply => reply.message_id === id)
) || MessagesData.find(msg => msg.latest_message.message_id === id) || MessagesData.find(msg => msg.parent_message_id === id)
console.log(msg);
// Collect recipients from dynamic email bars (instead of directly from the 'toField' input)
const emailBarElements = document.querySelectorAll('#emailBars .email-bar');
// Map over each email bar and extract the value (email)
const recipients = Array.from(emailBarElements)
.map(bar => bar.value.trim()) // Get the value of each email bar
.join(','); // Join the email values as a comma-separated string
console.log(recipients);
// If there are no recipients, alert the user
if (!recipients) {
alert('Please add a recipient.');
document.getElementById('ComposeBox').remove();
return;
}
const subject = document.getElementById('subject').value; // Fetch subject
const message = document.getElementById('message').value; // Fetch message
2 weeks ago
const attachment = document.getElementById('attachment-reply').files[0];
3 weeks ago
console.log(attachment);
// If both subject and message are empty, confirm whether to send the message
if (!subject && !message) {
const confirmSend = confirm('Send this message without a subject or text in the body?');
if (!confirmSend) {
return; // Stop execution if the user cancels
}
}
const old_message_id = id;
console.log(old_message_id);
2 weeks ago
const userId = document.getElementById('user_id').value;
3 weeks ago
// Append dynamic recipient information to the form data
const formData = new FormData(form);
formData.append('toField', recipients); // Use dynamically gathered recipients
formData.append('subject', subject);
formData.append('message', message);
formData.append('attachment', attachment);
formData.append('message_id', old_message_id);
const url = form.getAttribute('action');
console.log(url);
// Send the message using the fetch API
fetch(url, {
method: 'POST',
headers: {
'X-CSRFToken': '{{ csrf_token }}' // CSRF token for security
},
body: formData
})
.then(response => {
if (!response.ok) {
throw new Error('Failed to send message.');
}
return response.json();
})
.then(data => {
console.log(data);
if (data.status === 'success') {
alert('Message sent successfully!');
document.getElementById('ComposeBox').remove();
findMainMessageId(id).then(mainMessageId => {
console.log("Returned Main Message ID:", mainMessageId);
const parentMessageId = mainMessageId;
console.log(parentMessageId);
let repliesContainer = document.getElementById(`replies_${parentMessageId}`);
if (!repliesContainer) {
console.error(`Replies container not found for ID: replies_${parentMessageId}`);
return;
}
repliesContainer.innerHTML = ''; // Clear existing replies
fetch(`/fetch_replies/${parentMessageId}/?user_id=${userId}`)
.then(response => response.json())
.then(data => {
console.log("Replies fetched:", data);
renderReplies(data.replies, repliesContainer);
})
})
.catch(error => {
console.error('Error fetching replies:', error);
});
2 weeks ago
updateMessageNotification();
3 weeks ago
} else {
alert('Failed to send message. Please try again.');
}
})
.catch(error => {
console.error('Error:', error);
alert('An error occurred while sending the message.');
});
}
2 weeks ago
function updateMessageNotification() {
const userId = document.getElementById('user_id').value;
fetch(`/unread_message_count/?user_id=${userId}`)
.then(response => response.json())
.then(data => {
console.log('unread_count:',data.unread_count);
const notificationBadge = document.getElementById('messageNotificationBadge');
if (data.unread_count > 0) {
notificationBadge.textContent = data.unread_count ;
notificationBadge.style.display = 'inline-flex'; // Show badge if there are unread messages
} else {
notificationBadge.style.display = 'none'; // Hide badge if no unread messages
}
})
.catch(error => console.error('Error fetching unread message count:', error));
}
3 weeks ago
function forwardMessage(index) {
const message = window.Messages[index];
alert(`Forward: ${message.subject}`);
// Add functionality to open a forward form here
}
function toggleDeleteButton() {
// Select all checkboxes within the container dynamically
const checkboxes = document.querySelectorAll('input[type="checkbox"][id^="checkbox_"]'); // Matches all checkboxes with IDs starting with 'checkbox_'
const deleteButtons = document.querySelectorAll('span[id^="delete_"]'); // Matches all delete buttons with IDs starting with 'delete_'
checkboxes.forEach((checkbox) => {
const messageId = checkbox.getAttribute('data-message-id');
const deleteButton = document.getElementById(`delete_${messageId}`);
if (checkbox.checked) {
deleteButton.style.display = 'block'; // Show delete button for the specific message
} else {
deleteButton.style.display = 'none'; // Hide delete button if not checked
}
});
}
window.TrashMessages = {};
function deleteMessage(event, message_id) {
event.stopPropagation(); // Prevent parent events
// Fetch MessagesDetails and TrashMessages
const MessagesData = window.MessagesDetails;
const TrashMessages = window.TrashMessages || {};
console.log("All Messages:", MessagesData);
console.log("Message ID to delete:", message_id);
// Find the specific message in MessagesDetails
const messageIndex = MessagesData.findIndex(msg => msg.message_id === message_id);
if (messageIndex !== -1) {
const messageDetails = MessagesData[messageIndex];
console.log("Message Details to move:", messageDetails);
// Move the message to TrashMessages
TrashMessages[message_id] = messageDetails;
// Remove the message from MessagesData
MessagesData.splice(messageIndex, 1); // Remove the message from the array
console.log(`Message ${message_id} moved to trash.`);
console.log("Updated MessagesDetails:", MessagesData);
console.log("Updated TrashMessages:", TrashMessages);
// Update the `is_trashed` status in the backend
fetch(`/update_message_status/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': '{{csrf_token}}', // Include CSRF token if needed
},
body: JSON.stringify({
message_id: message_id,
is_trashed: true
})
})
.then(response => {
if (!response.ok) {
throw new Error(`Failed to update message status for ID ${message_id}`);
}
return response.json();
})
.then(data => {
console.log(`Message ${message_id} status updated successfully in the backend:`, data);
// Update the UI: Remove the message row
const messageRow = document.querySelector(`#checkbox_${message_id}`).closest('.emailRow');
if (messageRow) {
messageRow.remove();
console.log(`${message_id} removed from messages`);
} else {
console.warn(`Message row with ID ${message_id} not found in the DOM.`);
}
})
.catch(error => {
console.error(`Error updating message status for ID ${message_id}:`, error);
});
} else {
console.error(`Message with ID ${message_id} not found in MessagesDetails.`);
}
}
function renderTrashMessages() {
const sentContainer = document.getElementById('InboxContainer');
const userId = document.getElementById('user_id').value;
sentContainer.innerHTML = ''; // Clear container
console.log(userId);
fetch(`/render_trash_messages/?user_id=${userId}`) // Replace with the actual endpoint
.then(response => {
if (!response.ok) {
throw new Error('Failed to fetch trash messages');
}
return response.json();
})
.then(data => {
console.log('Trash data received:', data);
if (data.trash_messages.length === 0) {
sentContainer.innerHTML = `<h2>No messages found in trash</h2>`;
} else {
// Loop through the trash messages and render them
data.trash_messages.forEach((message) => {
const messageType = message.message_type === 'inbox' ? 'Received from' : 'Sent to';
console.log(messageType);
const emailRow = `
<div class="emailRow" style="border-bottom: 1px solid #ddd; padding: 10px; cursor: pointer;">
<div class="emailRow__options">
<input type="checkbox" id="checkbox_${message.message_id}"
data-message-id="${message.message_id}"
onchange="toggleDeleteButton()"
onclick="event.stopPropagation()" />
</div>
<h3 class="emailRow__title" style="font-weight: bold;">${messageType} ${message.sender_fullname || message.recipient_fullname}</h3>
<div class="emailRow__message" style="font-size: 0.9em; color: #555;">
<h4>${message.subject}
<span class="emailRow__description"> - ${message.body.substring(0, 50)}...</span>
</h4>
<span id="delete_${message.message_id}"
class="material-icons"
style="display: none; z-index: 1000;"
onclick="deleteMessage(event, '${message.message_id}')">delete</span>
</div>
<p class="emailRow__time" style="color: #aaa; font-size: 0.8em;">
${new Date(message.sent_at).toLocaleString()}
</p>
</div>
`;
sentContainer.innerHTML += emailRow;
});
window.MessagesDetails = data.trash_messages;
}
})
.catch(error => {
console.error('Error fetching trash messages:', error);
sentContainer.innerHTML = `<p>Error loading messages. Please try again later.</p>`;
});
}
function renderSentMessages() {
const inboxContainer = document.getElementById('InboxContainer');
2 weeks ago
inboxContainer.innerHTML = '';
const userId = document.getElementById('user_id').value;
3 weeks ago
2 weeks ago
fetch(`/render_sent_messages/?user_id=${userId}`)
.then(response => {
if (!response.ok) {
throw new Error('Failed to fetch inbox messages');
}
return response.json();
})
.then(data => {
console.log(data.sent_messages);
if (data.sent_messages.length === 0) {
inboxContainer.innerHTML = `<h2>No messages found</h2>`;
} else {
const uniqueMessages = {};
data.sent_messages.forEach(message => {
uniqueMessages[message.latest_message.message_id] = message;
});
Object.values(uniqueMessages).forEach(message => {
const latestMessage = message.latest_message;
// ✅ Set all sent messages as read (light grey background)
const rowStyle = 'background-color: #efeded;';
const textStyle = 'font-weight: normal; color: #555;';
const emailRow = `
<div class="emailRow" data-message-id="${latestMessage.message_id}" style="border-bottom: 1px solid #ddd; padding: 10px; ${rowStyle}" onclick="showMessageDetails('${latestMessage.message_id}')">
<div class="emailRow__options">
<input type="checkbox" id="checkbox" data-message-id="${latestMessage.message_id}" onchange="toggleDeleteButton()" onclick="event.stopPropagation()" />
</div>
${latestMessage.recipient_fullnames.join(',').length > 15 ?
`<h3 class="emailRow__title" style="${textStyle}">To: ${latestMessage.recipient_fullnames.join(',').substring(0, 15)}...</h3>`
: `<h3 class="emailRow__title" style="${textStyle}">To: ${latestMessage.recipient_fullnames.join(',')}</h3>`}
<div class="emailRow__message" style="font-size: 0.9em; ${textStyle}">
${latestMessage.subject ? `
<h4 style="${textStyle}">${latestMessage.subject}
<span class="emailRow__description"> - ${latestMessage.body.substring(0, 50)}...</span>
</h4>`
: `<span class="emailRow__description"> ${latestMessage.body.substring(0, 50)}...</span>`}
<span id="deleteButton" class="material-icons" style="display: none; z-index: 1000;" onclick="deleteMessage(event)">delete</span>
</div>
<p class="emailRow__time" style="color: black; font-size: 0.8em; ${textStyle}">${latestMessage.sent_at}</p>
</div>
`;
inboxContainer.innerHTML += emailRow;
});
window.MessagesDetails = data.sent_messages;
}
})
.catch(error => {
console.error('Error fetching inbox messages:', error);
inboxContainer.innerHTML = `<p>Error loading messages. Please try again later.</p>`;
});
}
3 weeks ago
function renderInbox() {
const inboxContainer = document.getElementById('InboxContainer');
inboxContainer.innerHTML = '';
const userId = document.getElementById('user_id').value;
fetch(`/render_messages/?user_id=${userId}`)
.then(response => {
if (!response.ok) {
throw new Error('Failed to fetch inbox messages');
}
return response.json();
})
.then(data => {
console.log(data.inbox_messages);
if (data.inbox_messages.length === 0) {
inboxContainer.innerHTML = `<h2>No messages found</h2>`;
} else {
// Clear duplicates by grouping messages by the latest message ID
const uniqueMessages = {};
data.inbox_messages.forEach(message => {
uniqueMessages[message.latest_message.message_id] = message;
});
// Render only the latest message for each group
Object.values(uniqueMessages).forEach(message => {
const latestMessage = message.latest_message;
2 weeks ago
const isUnread = !latestMessage.is_read;
const rowStyle = isUnread
? 'background-color: #fff;'
: 'background-color: #efeded;';
const textStyle = isUnread ? 'font-weight: bold;' : 'font-weight: normal;';
3 weeks ago
const emailRow = `
2 weeks ago
<div class="emailRow" data-message-id="${latestMessage.message_id}" style="border-bottom: 1px solid #ddd; padding: 10px; ${rowStyle}" onclick="showMessageDetails('${latestMessage.message_id}')">
3 weeks ago
<div class="emailRow__options">
2 weeks ago
<input type="checkbox" id="checkbox_${latestMessage.message_id}" data-message-id="${latestMessage.message_id}" onchange="toggleDeleteButton()" onclick="event.stopPropagation()" />
3 weeks ago
</div>
2 weeks ago
<h3 class="emailRow__title" style="${textStyle}">From: ${latestMessage.sender_fullname}</h3>
3 weeks ago
<div class="emailRow__message" style="font-size: 0.9em; color: #555;">
${latestMessage.subject ? `
2 weeks ago
<h4 style="${textStyle}">${latestMessage.subject}
<span class="emailRow__description"> - ${latestMessage.body.substring(0, 50)}...</span>
</h4>`
: `<span class="emailRow__description"> ${latestMessage.body.substring(0, 50)}...</span>`}
<span id="delete_${latestMessage.message_id}" class="material-icons" style="display: none; cursor: pointer; color: gray; transition: color 0.2s ease-in-out, transform 0.2s ease-in-out; position: absolute; right: 230px;" onclick="deleteMessage(event, '${latestMessage.message_id}')"
onmouseover="this.style.color='red'; this.style.transform='scale(1.2)';" onmouseout="this.style.color='gray'; this.style.transform='scale(1)';">
delete </span>
3 weeks ago
</div>
2 weeks ago
<p class="emailRow__time" style="color: black; font-size: 0.8em; ${textStyle}">${latestMessage.sent_at}</p>
3 weeks ago
</div>
`;
inboxContainer.innerHTML += emailRow;
});
window.MessagesDetails = data.inbox_messages;
}
})
.catch(error => {
console.error('Error fetching inbox messages:', error);
inboxContainer.innerHTML = `<p>Error loading messages. Please try again later.</p>`;
});
}
2 weeks ago
function showFileName() {
var input = document.getElementById("attachment-input");
var fileNameDisplay = document.getElementById("file-name");
if (input.files.length > 0) {
var fullFileName = input.files[0].name;
var maxLength = 40; // Max characters before truncating
if (fullFileName.length > maxLength) {
var truncatedFileName = fullFileName.substring(0, maxLength) + "...";
fileNameDisplay.textContent = truncatedFileName;
} else {
fileNameDisplay.textContent = fullFileName;
}
} else {
fileNameDisplay.textContent = ""; // Clear if no file is selected
}
}
3 weeks ago
function sendMessage(event) {
event.preventDefault();
const form = document.getElementById('ComposeMessage');
const toField = document.getElementById('toField').value; // Fetch 'to' field value
const subject = document.getElementById('subject').value; // Fetch subject
const message = document.getElementById('Message').value; // Fetch message
2 weeks ago
const attachmentInput = document.getElementById('attachment-input');
const fileNameDisplay = document.getElementById('file-name');
3 weeks ago
const recipients = toField.split(',').map(email => email.trim()).filter(email => email !== '');
console.log(recipients);
if (!toField) {
alert('Please add a recipient.');
return; // Stop execution
}
if (!subject && !message) {
const confirmSend = confirm('Send this message without a subject or text in the body?');
if (!confirmSend) {
return; // Stop execution if the user cancels
}
}
const formData = new FormData(form);
formData.append('toField', recipients.join(','));
formData.append('subject', subject);
formData.append('message', message);
formData.append('attachment', attachment);
const url = form.getAttribute('action');
fetch(url, {
method: 'POST',
headers: {
'X-CSRFToken': '{{ csrf_token }}' // CSRF token for security
},
body: formData
})
.then(response => response.json())
.then(data => {
console.log(data);
if (data.status === 'success') {
alert('Message sent successfully!');
form.reset();
2 weeks ago
fileNameDisplay.innerHTML= '';
3 weeks ago
document.getElementById('ComposeContainer').style.display = 'none';
<!-- reloadMessages();-->
} else {
alert('Message not sent');
}
})
.catch(error => {
console.error('Error:', error);
});
2 weeks ago
3 weeks ago
}
<!--document.addEventListener('click', function(event) {-->
<!-- const searchKeyword = document.getElementById('toField')-->
<!-- if (!searchKeyword) return;-->
<!-- function handleInternalEmployees() {-->
<!-- const keyword = searchKeyword.value.trim();-->
<!-- console.log('keyword1:',keyword);-->
<!-- if (keyword === '') {-->
<!-- const autocompleteDropdown = document.getElementById('autocompleteDropdown');-->
<!-- autocompleteDropdown.innerHTML = '';-->
<!-- return;-->
<!-- }-->
<!-- getInternalEmployees();-->
<!-- }-->
<!-- function getInternalEmployees() {-->
<!-- const searchKeyword = document.getElementById('toField').value;-->
<!-- console.log('keyword2:',searchKeyword);-->
<!-- let xhr = new XMLHttpRequest();-->
<!-- xhr.open('GET', `/skyonnadmin/get_InternalEmployees/?toField=${searchKeyword}`, true);-->
<!-- xhr.onload = function() {-->
<!-- if (xhr.status === 200) {-->
<!-- filteredData = JSON.parse(xhr.responseText);-->
<!-- console.log(filteredData);-->
<!-- renderAutocompleteDropdown(filteredData)-->
<!-- } else {-->
<!-- console.error('Request failed. Status: ' + xhr.status);-->
<!-- }-->
<!-- };-->
<!-- xhr.send();-->
<!-- }-->
<!-- searchKeyword.addEventListener('input', handleInternalEmployees);-->
<!--});-->
<!-- function renderAutocompleteDropdown(data) {-->
<!-- const autocompleteDropdown = document.getElementById('autocompleteDropdown');-->
<!-- autocompleteDropdown.innerHTML = '';-->
<!-- console.log(data.employees.length);-->
<!-- if (data.employees.length === 0) {-->
<!-- return;-->
<!-- }-->
<!-- else {-->
<!-- data.employees.forEach((employee)=> {-->
<!-- const box = document.createElement('div')-->
<!-- box.className = 'autocomplete-box';-->
<!-- box.innerHTML = `-->
<!-- <div class="employee-name">${employee.FirstName} ${employee.LastName}</div>-->
<!-- <div class="employee-email">${employee.Email1 || employee.Email2}</div>-->
<!-- `;-->
<!-- box.textContent =`${employee.FirstName} ${employee.LastName} <${employee.Email1}>`-->
<!-- box.addEventListener('click', function() {-->
<!-- const toField = document.getElementById('toField');-->
<!-- toField.value = `${employee.Email1}`;-->
<!-- autocompleteDropdown.style.display = 'none';-->
<!-- })-->
<!--&lt;!&ndash; box.style.display = 'block'&ndash;&gt;-->
<!-- autocompleteDropdown.appendChild(box);-->
<!-- console.log(box.textContent)-->
<!-- });-->
<!-- console.log(autocompleteDropdown.style.display);-->
<!-- autocompleteDropdown.style.display = 'block';-->
<!-- }-->
<!-- }-->
document.addEventListener("click", function (event) {
if (event.target && event.target.matches('#compose')) {
const compose = document.getElementById('compose');
if (compose) {
showDetails();
}
}
});
function showDetails() {
console.log('details')
const toField = document.getElementById("toField");
const emailDropdown = document.getElementById("emailCheckbox");
const dropdownIcon = document.getElementById("dropdownIcon");
// Function to show the dropdown
function showDropdown() {
emailDropdown.style.display = "block";
dropdownIcon.innerHTML = "&#9650;"; // Up arrow
}
// Function to hide the dropdown
function hideDropdown() {
emailDropdown.style.display = "none";
dropdownIcon.innerHTML = "&#9660;"; // Down arrow
}
// Toggle dropdown when clicking the input or dropdown icon
toField.addEventListener("click", function (event) {
event.stopPropagation();
showDropdown();
});
dropdownIcon.addEventListener("click", function (event) {
event.stopPropagation();
showDropdown();
});
// Hide dropdown when clicking outside
document.addEventListener("click", function (event) {
if (!toField.contains(event.target) && !emailDropdown.contains(event.target) && !dropdownIcon.contains(event.target)) {
hideDropdown();
}
});
// Handling checkbox selection
const checkboxes = document.querySelectorAll(".email-checkbox");
checkboxes.forEach((checkbox) => {
checkbox.addEventListener("change", function () {
const selectedEmails = Array.from(checkboxes)
.filter((checkbox) => checkbox.checked)
.map((checkbox) => checkbox.value);
toField.value = selectedEmails.join(", ");
});
});
}
function showCompose(event) {
event.preventDefault();
const composeContainer = document.getElementById('ComposeContainer');
const toField = document.getElementById("toField");
const subjectField = document.getElementById("subject");
const messageField = document.getElementById("Message");
const emailCheckboxes = document.querySelectorAll(".email-checkbox");
// Clear input fields when opening compose
if (toField) toField.value = "";
if (subjectField) subjectField.value = "";
if (messageField) messageField.value = "";
emailCheckboxes.forEach((checkbox) => {
checkbox.checked = false;
});
composeContainer.style.display = 'block';
}
function CloseCompose(event) {
event.preventDefault();
document.getElementById('ComposeContainer').style.display = 'none';
}
// messages //
2 months ago
document.addEventListener('DOMContentLoaded', function() { //to show popup of job posting details for jobId in all job posting
document.addEventListener('click', function(event) {
if (event.target && event.target.matches('.jobId-link')) {
event.preventDefault();
const jobId = event.target.getAttribute('data-JobId');
let xhr = new XMLHttpRequest();
xhr.open('GET', `/get_jobPosting/?JobId=${encodeURIComponent(jobId)}`, true);
xhr.onload = function() {
if (xhr.status === 200) {
const details = JSON.parse(xhr.responseText);
console.log('Details received:', details);
showPopup(details);
} else {
console.error('Request failed. Status:', xhr.status);
}
};
xhr.send();
}
});
function showPopup(data) {
const popup = document.getElementById('detailsModal2');
if (popup) {
// Fill in the popup with data
document.getElementById('Client').textContent = (data.Client || '');
document.getElementById('JobID').textContent = (data.JobID || '');
document.getElementById('Location').textContent = (data.Location || '');
document.getElementById('SPOC').textContent = (data.SPOC || '');
document.getElementById('SPOC2').textContent = (data.SPOC2 || '');
document.getElementById('NoOfPosting').textContent = (data.NoOfPosting || '');
document.getElementById('StartDate').textContent = (data.StartDate || '');
document.getElementById('CloseDate').textContent = (data.CloseDate || '');
document.getElementById('Experience_in_Yrs').textContent = (data.Experience_in_Yrs || '');
document.getElementById('BudgetMin').textContent = (data.BudgetMin || '');
document.getElementById('Qualification').textContent = (data.Qualification || '');
document.getElementById('Header').textContent = (data.Header || '');
document.getElementById('JobDescription').textContent = (data.JobDescription || '');
document.getElementById('SpecialInstructions').textContent = (data.SpecialInstructions || '');
// Attach the close button event listener each time the popup is shown
document.getElementById('closePopup2').addEventListener('click', function() {
popup.style.display = 'none';
});
// Display the popup
popup.style.display = 'block';
} else {
console.error('Popup element not found');
}
}
});
function validateSalary() {
var minSalary = parseInt(document.getElementById("minAmount").value);
var maxSalary = parseInt(document.getElementById("maxAmount").value);
if (maxSalary <= minSalary) {
alert("max salary must be greater than min salary.");
document.getElementById("maxAmount").value = "";
document.getElementById("maxAmount").focus();
}
}
document.addEventListener('input', function (event) {
var target = event.target;
if (target && target.id === 'maxAmount') {
const amount = target.value.trim();
if (!amount.trim()) {
document.getElementById('Salary').textContent = '';
return;
}
if (!/^\d+(\.\d+)?$/.test(amount) || parseFloat(amount) < 1) {
document.getElementById('Salary').textContent = 'Invalid input';
return;
}
const num = parseFloat(amount.replace(/,/g, '')); // Remove commas and parse to a number
const formattedSalary = SalaryToWords(num);
document.getElementById('Salary').textContent = formattedSalary + ' rupees';
}
});
document.addEventListener('input', function (event) {
var target = event.target;
if (target && target.id === 'minAmount') {
const amount = target.value.trim();
if (!amount.trim()) {
document.getElementById('Salary').textContent = '';
return;
}
if (!/^\d+(\.\d+)?$/.test(amount) || parseFloat(amount) < 1) {
document.getElementById('Salary').textContent = 'Invalid input';
return;
}
const num = parseFloat(amount.replace(/,/g, '')); // Remove commas and parse to a number
const formattedSalary = SalaryToWords(num);
document.getElementById('Salary').textContent = formattedSalary + ' rupees';
}
});
window.SalaryToWords = function (num) {
const ones = [
'', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine',
'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen',
'seventeen', 'eighteen', 'nineteen',
];
const tens = [
'', '', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety',
];
const scales = ['crore', 'lakh', 'thousand', 'hundred', '']; // Indian number system
const scaleNumbers = [10000000, 100000, 1000, 100, 1];
if (num === 0) return 'zero';
let result = '';
let remainder = num;
for (let i = 0; i < scales.length; i++) {
const scaleValue = Math.floor(remainder / scaleNumbers[i]);
remainder %= scaleNumbers[i];
if (scaleValue > 0) {
if (scaleNumbers[i] >= 100) {
result += `${SalaryToWords(scaleValue)} ${scales[i]} `;
} else if (scaleValue < 20) {
result += `${ones[scaleValue]} `;
} else {
result += `${tens[Math.floor(scaleValue / 10)]} ${ones[scaleValue % 10]} `;
}
}
}
return result.trim(); // Remove extra spaces
};
function toggleConditionalFields() {
const budgetDropdown = document.getElementById('BudgetMin');
const conditionalFields = document.getElementById('conditionalFields');
const minAmount = document.getElementById('minAmount');
const maxAmount = document.getElementById('maxAmount');
let industryText = document.getElementById('industryText');
const amountFields = document.getElementById('amountFields');
const minSalary = document.getElementById('Salary');
// Create and position the 'Please Select Salary' text if it doesn't already exist
if (!industryText) {
industryText = document.createElement('p');
industryText.id = 'industryText';
industryText.style.position = 'fixed';
industryText.style.marginLeft = '820px';
industryText.style.marginTop = '-325px';
document.body.appendChild(industryText);
}
if (budgetDropdown.value === "Fixed") {
// Show fields for Fixed budget
conditionalFields.style.display = "block";
timePeriodWrapper.style.display = "flex";
industryText.style.marginTop = '-319px';
amountFields.style.marginLeft = '640px';
minAmount.style.marginLeft = '-100px';
maxAmount.style.marginLeft = '-100px';
minSalary.textContent = '';
minAmount.value = "";
maxAmount.value = "";
}
else if (budgetDropdown.value === "Industry Standard") {
// Show fields for Industry Standard
conditionalFields.style.display = "block";
timePeriodWrapper.style.display = "none";
industryText.style.marginTop = '-320px';
amountFields.style.marginLeft = '480px';
minAmount.style.marginLeft = '-160px';
maxAmount.style.marginLeft = '-100px';
minSalary.textContent = '';
minAmount.value = "";
maxAmount.value = "";
}else {
// Hide all fields for other options
conditionalFields.style.display = "none";
timePeriodWrapper.style.display = "none";
industryText.style.marginTop = '-100px';
}
}
// Function to convert number to words
function numberToWords(num) {
const belowTen = ["", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"];
const belowTwenty = ["Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"];
const belowHundred = ["", "", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"];
if (num === 0) return "Zero";
// Function for recursive processing
function convert(num) {
if (num < 10) return belowTen[num];
if (num < 20) return belowTwenty[num - 10];
if (num < 100) return belowHundred[Math.floor(num / 10)] + (num % 10 ? " " + belowTen[num % 10] : "");
if (num < 1000) return belowTen[Math.floor(num / 100)] + " Hundred" + (num % 100 ? " " + convert(num % 100) : "");
if (num < 1000000) return convert(Math.floor(num / 1000)) + " Thousand" + (num % 1000 ? " " + convert(num % 1000) : "");
if (num < 1000000000) return convert(Math.floor(num / 1000000)) + " Million" + (num % 1000000 ? " " + convert(num % 1000000) : "");
}
return convert(num);
}
// Function to handle input change and convert numbers to words
function convertInputToWords(inputElement) {
let inputValue = inputElement.value;
const numericValue = parseInt(inputValue.replace(/[^0-9]/g, '')); // Remove non-numeric characters
if (!isNaN(numericValue)) {
const wordValue = numberToWords(numericValue);
inputElement.value = wordValue; // Update input value with the word
}
}
document.addEventListener('DOMContentLoaded', function() {
document.addEventListener('change', function(event) {
var target = event.target;
if (target && target.id === 'ClientDropdown') {
var parentCompany = target.value; // Get selected client
var subClientDropdown = target.closest('form').querySelector('#SubClientDropdown');
var formId = target.closest('form').id;
// Make an AJAX request to fetch sub-clients filtered by selected client
var xhr = new XMLHttpRequest();
xhr.open('GET', '/skyonnadmin/get_subclients/?parent_company=' + parentCompany, true);
xhr.onload = function() {
if (xhr.status === 200) {
subClientDropdown.innerHTML = '<option value="">Select SubClient</option>';
var subClients = JSON.parse(xhr.responseText);
subClients.forEach(function(subClient) {
var option = document.createElement('option');
option.value = subClient;
option.text = subClient;
subClientDropdown.appendChild(option);
});
} else {
console.error('Request failed. Status: ' + xhr.status);
}
};
xhr.send();
}
});
});
function goBack() {
document.getElementById("addContactPopup").style.display = "none";
}
document.getElementById('newJobPosting').addEventListener('click', function () {
const main = document.getElementById('dynamicContentContainer');
main.style.display ='none';
setTimeout(function () {
const container = document.getElementById('jobPostingForm');
const restricted = document.getElementById('restrictedField').value;
console.log('Restricted value:', restricted);
if (restricted === 'True') { // Check against 'True', not 'true'
console.log('Access is restricted');
alert('You are assigned a level above 5. You cannot access New job posting page');
container.style.display='none';
}
else {
main.style.display='block';
}
}, 100)
});
function validateLength(input) {
const maxLength = 8;
if (input.value.length > maxLength) {
input.value = input.value.slice(0, maxLength);
}
}
document.getElementById('allJobPosting').addEventListener('click', function () {
setTimeout(function () {
const container = document.getElementById('AllJobPostingTable');
const restricted = document.getElementById('restrictedField').value;
console.log('Restricted value:', restricted);
if (restricted === 'True') {
console.log('Access is restricted');
alert('You are assigned a level below 5. You cannot access All job postings page');
container.style.display='none';
}
}, 100)
});
11 months ago
let menu = document.querySelector('.menu')
let sidebar = document.querySelector('.sidebar')
let mainContent = document.querySelector('.main--content')
menu.onclick = function() {
sidebar.classList.toggle('active')
mainContent.classList.toggle('active')
}
2 months ago
function loadUserPage(pageName, userId) {
var urlWithUserId = pageName + "?user_id=" + userId; // Append admin_id as query parameter
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("dynamicContentContainer").innerHTML = this.responseText;
}
};
xhttp.open("GET", urlWithUserId, true);
xhttp.send();
}
<!-- function activateSidebarLink(clickedLink) {-->
<!-- // Remove 'active' class from all sidebar links-->
<!-- var sidebarLinks = document.querySelectorAll('.sidebar-link');-->
<!-- sidebarLinks.forEach(function(link) {-->
<!-- link.classList.remove('active');-->
<!-- });-->
<!-- // Add 'active' class to the clicked sidebar link-->
<!-- clickedLink.classList.add('active');-->
<!-- }-->
document.addEventListener('DOMContentLoaded', function() { //to show popup for client details
document.addEventListener('click', function(event) {
if (event.target && event.target.matches('.client-link')) {
event.preventDefault();
const client = event.target.getAttribute('data-client');
let xhr = new XMLHttpRequest();
xhr.open('GET', `/get_client_details/?client=${encodeURIComponent(client)}`, true);
xhr.onload = function() {
if (xhr.status === 200) {
const details = JSON.parse(xhr.responseText);
console.log('Details received:', details);
showPopup(details);
} else {
console.error('Request failed. Status:', xhr.status);
}
};
xhr.send();
}
});
function showPopup(data) {
const popup = document.getElementById('detailsModal');
console.log('Popup element:', popup); // Check if popup is found
if (popup) {
// Fill in the popup with data
document.getElementById('parentCompany').textContent = (data.parent_company || '');
document.getElementById('gstNo').textContent = (data.GST_No || '');
document.getElementById('locationId').textContent = (data.Location_Id || '');
document.getElementById('address1').textContent = (data.Address_1 || '');
document.getElementById('address2').textContent = (data.Address_2 || '');
document.getElementById('city').textContent = (data.City || '');
document.getElementById('state').textContent = (data.State || '');
document.getElementById('pincode').textContent = (data.Pincode || '');
document.getElementById('country').textContent = (data.Country || '');
// Attach the close button event listener each time the popup is shown
document.getElementById('closePopup').addEventListener('click', function() {
popup.style.display = 'none';
});
// Display the popup
popup.style.display = 'block';
} else {
console.error('Popup element not found');
}
}
});
document.addEventListener('DOMContentLoaded', function() {
document.addEventListener('change', function(event) {
var target = event.target;
if (target && target.id === 'Client') {
var client = target.value; // Get selected client
let SPOC1 = document.getElementById('SPOC');
if (!SPOC1) return;
let SPOC2 = document.getElementById('SPOC2');
if (!SPOC2) return;
SPOC1.innerHTML = '<option value="">Select SPOC1</option>';
SPOC2.innerHTML = '<option value="">Select SPOC2</option>';
// Make AJAX request to get filtered data
let xhr = new XMLHttpRequest();
xhr.open('GET', '/get_contacts/?Client=' + client, true);
xhr.onload = function() {
if (xhr.status === 200) {
var spocData = JSON.parse(xhr.responseText);
spocData.forEach(function(contact) {
const option1 = document.createElement('option');
option1.value = `${contact.FirstName} ${contact.LastName}`;
option1.textContent = `${contact.FirstName} ${contact.LastName}`;
SPOC1.appendChild(option1);
const option2 = document.createElement('option');
option2.value = `${contact.FirstName} ${contact.LastName}`;
option2.textContent = `${contact.FirstName} ${contact.LastName}`;
SPOC2.appendChild(option2);
});
} else {
console.error('Request failed. Status: ' + xhr.status);
}
};
xhr.onerror = function() {
console.error('Request failed.');
};
xhr.send();
}
})
});
document.addEventListener('DOMContentLoaded', function() {
document.addEventListener('change', function() {
const form = document.getElementById('AddSPOCform');
if (!form) return;
const emailInput = document.getElementById('Email');
const phoneNumberInput = document.getElementById('Phone_number');
const requiredFields = form.querySelectorAll('input[required], select[required]');
const validateField = (field) => {
if (!field.value.trim()) {
field.style.borderColor = '';
field.setCustomValidity('Please fill out this field.');
field.reportValidity();
return false;
} else {
field.style.borderColor = 'black';
field.setCustomValidity('');
return true;
}
};
const clearValidation = (field) => {
field.setCustomValidity('');
field.style.borderColor = '';
};
emailInput.addEventListener('input', () => {
clearValidation(emailInput);
});
phoneNumberInput.addEventListener('input', () => {
clearValidation(phoneNumberInput);
});
emailInput.addEventListener('blur', () => {
if (emailInput.value.trim() && (!emailInput.value.match(/^[^\s@]+@[^\s@]+\.[a-zA-Z]{2,}$/) || emailInput.value.includes('..') || !emailInput.value.match(/^[^\s@]{1,64}@([^\s@_]+\.)+[a-zA-Z]{2,}$/))) {
emailInput.style.borderColor = '';
emailInput.setCustomValidity('Invalid email format.');
emailInput.reportValidity();
} else {
clearValidation(emailInput);
if (emailInput.value.trim()) {
checkFieldExists('Email', emailInput);
}
}
});
phoneNumberInput.addEventListener('blur', () => {
if (phoneNumberInput.value.trim() && !phoneNumberInput.value.match(/^[6-9]\d{9}$/)) {
phoneNumberInput.style.borderColor = '';
phoneNumberInput.setCustomValidity('Invalid phone number format.');
phoneNumberInput.reportValidity();
} else {
clearValidation(phoneNumberInput);
if (phoneNumberInput.value.trim()) {
checkFieldExists('Phone_number', phoneNumberInput);
}
}
});
function checkFieldExists(fieldName, field) {
const value = field.value.trim();
fetch(`/validate_field/?${fieldName}=${value}`)
.then(response => response.json())
.then(data => {
if (data.exists) {
if (fieldName === 'Phone_number') {
field.setCustomValidity('Phone number already exists.');
} else {
field.setCustomValidity('Email already exists.');
}
field.style.borderColor = 'red';
field.reportValidity();
} else {
field.setCustomValidity('');
field.style.borderColor = 'black';
}
})
.catch(error => {
console.error('Error:', error);
});
}
})
});
window.saveAdd_SPOC = async function() {
const form = document.getElementById('AddSPOCform');
const requiredFields = form.querySelectorAll('input[required], select[required]');
const emailInput = document.getElementById('Email');
const phoneNumberInput = document.getElementById('Phone_number');
let isValid = true;
requiredFields.forEach(field => {
field.setCustomValidity('');
field.style.borderColor = '';
});
for (let field of requiredFields) {
if (!field.value.trim()) {
isValid = false;
field.setCustomValidity('Please fill out this field.');
field.reportValidity();
}
}
const validateEmail = (emailInput) => {
if (emailInput.value.trim() && (!emailInput.value.match(/^[^\s@]+@[^\s@]+\.[a-zA-Z]{2,}$/) || emailInput.value.includes('..') || !emailInput.value.match(/^[^\s@]{1,64}@([^\s@_]+\.)+[a-zA-Z]{2,}$/))) {
isValid = false;
emailInput.style.borderColor = '';
emailInput.setCustomValidity('Please enter a valid Email address');
emailInput.reportValidity();
}
else {
emailInput.setCustomValidity('');
emailInput.style.borderColor = 'black';
}
}
const checkValidity = (field,pattern,errorMsg) =>{
if (field.value.trim() && !field.value.match(pattern)) {
field.setCustomValidity(errorMsg);
field.reportValidity();
isValid=false;
}
else {
field.setCustomValidity('');
field.style.borderColor = 'black';
}
};
checkValidity(phoneNumberInput, /^[6-9]\d{9}$/, 'Invalid Phone number format.');
validateEmail(emailInput);
if (!isValid) {
console.log("Validation failed. Please fill out the required fields.");
return;
}
const checkFieldExists = (fieldName, field) => {
return new Promise((resolve, reject) => {
const value = field.value.trim();
fetch(`/validate_field/?${fieldName}=${value}`)
.then(response => response.json())
.then(data => {
if (data.exists) {
if (fieldName === 'Phone_number') {
field.setCustomValidity('Phone number already exists.');
} else {
field.setCustomValidity('Email already exists.');
}
field.style.borderColor = 'red';
field.reportValidity();
resolve(false);
} else {
field.setCustomValidity('');
field.style.borderColor = 'black';
resolve(true);
}
})
.catch(error => {
console.error('Error:', error);
reject(error);
});
});
}
const phoneNoValid = await checkFieldExists('Phone_number', phoneNumberInput);
const emailValid = await checkFieldExists('Email', emailInput);
isValid = isValid && phoneNoValid && emailValid;
if (!isValid) {
console.log("Validation failed. Please fill out the required fields.");
return;
}
const formData = new FormData(form);
const url = form.getAttribute('action');
console.log("Submitting form to:", url);
console.log("Form data:", [...formData.entries()]); // Log the form data
fetch(url, {
method: 'POST',
body: formData,
headers: {
'X-CSRFToken': '{{ csrf_token }}',
},
})
.then(response => {
if (!response.ok) {
throw new Error('Failed to save contact');
}
return response.json();
})
.then(data => {
console.log('Success:', data);
form.reset();
hidePopup();
showSuccessPopup();
})
.catch(error => {
console.error('Error:', error);
})
}
function refreshSPOCs() { //to refresh SPOC when refresh button clicked
console.log('refreshing SPOCs');
let client = document.getElementById('Client').value;
let SPOC1 = document.getElementById('SPOC');
if (!SPOC1) return;
let SPOC2 = document.getElementById('SPOC2');
if (!SPOC2) return;
SPOC1.innerHTML = '<option value="">Select SPOC1</option>';
SPOC2.innerHTML = '<option value="">Select SPOC2</option>';
// Make AJAX request to get filtered data
let xhr = new XMLHttpRequest();
xhr.open('GET', '/get_contacts/?Client=' + client, true);
xhr.onload = function() {
if (xhr.status === 200) {
var spocData = JSON.parse(xhr.responseText);
spocData.forEach(function(contact) {
const option1 = document.createElement('option');
option1.value = `${contact.FirstName} ${contact.LastName}`;
option1.textContent = `${contact.FirstName} ${contact.LastName}`;
SPOC1.appendChild(option1);
const option2 = document.createElement('option');
option2.value = `${contact.FirstName} ${contact.LastName}`;
option2.textContent = `${contact.FirstName} ${contact.LastName}`;
SPOC2.appendChild(option2);
});
} else {
console.error('Request failed. Status: ' + xhr.status);
}
};
xhr.onerror = function() {
console.error('Request failed.');
};
xhr.send();
}
function limitNumberOfPostings(input) {
var maxPostings = 100;
if (input.value > maxPostings) {
input.value = maxPostings; // Set the value to the maximum allowed
}
}
function updateInputField() {
var selectedStatesInput = document.getElementById("selectedStatesInput");
var selectedStates = [];
var checkboxes = document.querySelectorAll('input[type="checkbox"]:checked');
for (var i = 0; i < checkboxes.length; i++) {
selectedStates.push(checkboxes[i].value);
}
selectedStatesInput.value = selectedStates.join(", ");
// Close the dropdown after updating the input field
var dropdownContent = document.getElementById("checkboxContainer");
dropdownContent.style.display = "none";
}
function toggleOtherInputField() {
var otherCheckbox = document.getElementById("OtherCheckbox");
var selectedStatesInput = document.getElementById("selectedStatesInput");
var dropdownContent = document.getElementById("checkboxContainer");
if (otherCheckbox.checked) {
// Show the modal for adding a new location
showAddLocationModal();
dropdownContent.style.display = "none";
} else {
// If "Other" is unchecked, clear the input field, make it readonly again, and show dropdown content
selectedStatesInput.value = "";
selectedStatesInput.readOnly = true;
dropdownContent.style.display = "block";
}
}
function toggleDropdown() {
var dropdownContent = document.getElementById("checkboxContainer");
if (dropdownContent.style.display === "none") {
dropdownContent.style.display = "block";
} else {
dropdownContent.style.display = "none";
}
}
function showAddLocationModal() {
document.getElementById("addLocationModal").style.display = "block";
}
function closeAddLocationModal() {
document.getElementById("addLocationModal").style.display = "none";
document.getElementById("OtherCheckbox").checked = false;
}
function saveNewLocation() {
var newLocation = document.getElementById("newLocationInput").value.trim();
var selectedStatesInput = document.getElementById("selectedStatesInput");
if (newLocation) {
// Add new location to the dropdown
addLocationToDropdown(newLocation);
// Save new location to local storage
saveLocation(newLocation);
// Update the input field with the new location
var currentInput = selectedStatesInput.value;
selectedStatesInput.value = currentInput ? currentInput + ", " + newLocation : newLocation;
// Clear and reset the input field
document.getElementById("newLocationInput").value = "";
closeAddLocationModal();
} else {
alert("Please enter a location.");
}
}
function addLocationToDropdown(location) {
var checkboxContainer = document.getElementById("checkboxItems");
if (!checkboxContainer) {
return;
}
var newCheckbox = document.createElement("input");
newCheckbox.type = "checkbox";
newCheckbox.value = location;
newCheckbox.style.marginLeft = "-50px";
newCheckbox.id = "checkbox_" + location.replace(/\s+/g, '_');
newCheckbox.name = "checkbox_" + location.replace(/\s+/g, '_');
newCheckbox.onchange = updateInputField;
var newCheckboxLabel = document.createElement("label");
newCheckboxLabel.style.marginLeft = "-48px";
newCheckboxLabel.setAttribute("for", newCheckbox.id);
newCheckboxLabel.appendChild(document.createTextNode(" " + location));
checkboxContainer.appendChild(newCheckbox);
checkboxContainer.appendChild(newCheckboxLabel);
checkboxContainer.appendChild(document.createElement("br"));
}
function saveLocation(location) {
var locations = JSON.parse(localStorage.getItem('locations')) || [];
locations.push(location);
localStorage.setItem('locations', JSON.stringify(locations));
}
function loadLocations() {
var locations = JSON.parse(localStorage.getItem('locations')) || [];
locations.forEach(function(location) {
addLocationToDropdown(location);
});
}
document.addEventListener('DOMContentLoaded',function() {
document.addEventListener('change',function(event) {
var target = event.target;
if (target && target.id === 'Client') {
var client = target.value;
let xhr= new XMLHttpRequest();
xhr.open('GET',`/get_locations/?Client=${client}`,true);
xhr.onload = function() {
if (xhr.status === 200) {
const locations = JSON.parse(xhr.responseText);
updateCheckboxItems(locations);
} else {
console.error('Request failed. Status: ' + xhr.status);
}
};
xhr.send()
}
function updateCheckboxItems(locations) {
const checkboxItems = document.getElementById('checkboxItems');
checkboxItems.innerHTML = `
<input type="checkbox" id="anyWhereCheckbox" name="anyWhereCheckbox" value="Anywhere" onchange="updateInputField()" style="margin-left: -50px;">
<label for="anyWhereCheckbox" style="margin-left: -50px;">Anywhere</label><br>
`;
locations.forEach(function(location) {
const existingLocation = checkboxItems.querySelector(`input[value="${location}"]`)
if (!existingLocation) {
// Create a checkbox and label for each location
const checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.name = location;
checkbox.value = location;
checkbox.style.marginLeft = '-50px';
checkbox.onchange = updateInputField;
const label = document.createElement('label');
label.textContent = location;
label.style.marginLeft = '-45px';
label.htmlFor = location;
// Append checkbox and label to the container
checkboxItems.appendChild(checkbox);
checkboxItems.appendChild(label);
checkboxItems.appendChild(document.createElement('br'));
}
});
}
});
});
function showPopup() {
document.getElementById('addContactPopup').style.display = 'flex';
}
function hidePopup() {
document.getElementById('addContactPopup').style.display = 'none';
}
function showSuccessPopup() {
document.getElementById('successPopup').style.display = 'flex';
}
function hideSuccessPopup() {
document.getElementById('successPopup').style.display = 'none';
}
// Function to validate the job posting form (to be implemented)
function saveJobPosting() {
// Add your form validation and submission logic here
alert('Job posting saved!');
}
function saveJobPosting() {
const form = document.getElementById('jobPostingForm');
const orderedFieldIds = [
'Client', 'JobID', 'selectedStatesInput', 'SPOC', 'SPOC2',
'NoOfPosting', 'StartDate', 'CloseDate', 'Type', 'Experience',
'BudgetMin', 'timePeriod','minAmount','maxAmount', 'Header', 'JobDescription', 'SpecialInstructions', 'JD'
];
const minSalary = document.getElementById('minSalary');
const maxSalary = document.getElementById('maxSalary');
const minAmount = document.getElementById('minAmount');
const maxAmount = document.getElementById('maxAmount');
let isValid = true;
let firstInvalidField = null;
// Clear any previous custom validation messages and reset border colors
orderedFieldIds.forEach(id => {
const field = document.getElementById(id);
if (field) {
field.setCustomValidity(''); // Clear previous validation message
field.style.borderColor = ''; // Reset border color
}
});
// Iterate over each field in the specified order to validate
for (let id of orderedFieldIds) {
const field = document.getElementById(id);
if (field && !field.value.trim() && field !== 'JD') {
isValid = false;
field.setCustomValidity('Please fill out this field.');
field.reportValidity();
// Focus the first invalid field
if (!firstInvalidField) {
firstInvalidField = field;
}
break;
}
if (field && field === 'JD' && !field.value.trim()) {
isValid = false;
field.setCustomValidity('Please upload a file');
field.reportValidity();
if (!firstInvalidField) {
firstInvalidField = field;
}
}
}
if (minSalary && minSalary.textContent === 'Invalid input') {
isValid = false;
minAmount.setCustomValidity('Please enter correct salary amount.');
minAmount.reportValidity();
if (!firstInvalidField) {
firstInvalidField = minAmount;
}
}
if (!isValid) {
// Focus on the first invalid field according to the specified order
if (firstInvalidField) {
firstInvalidField.focus();
}
console.log("Validation failed. Please fill out the required fields.");
return;
}
// Proceed with saving data if all fields are valid
const formData = new FormData(form);
const url = form.getAttribute('action');
console.log("Submitting form to:", url);
console.log("Form data:", [...formData.entries()]); // Log the form data
fetch(url, {
method: 'POST',
body: formData,
headers: {
'X-CSRFToken': '{{ csrf_token }}', // Assuming you have CSRF token available
},
})
.then(response => {
if (!response.ok) {
throw new Error('Failed to save job posting.');
}
return response.json();
})
.then(data => {
console.log('Success:', data);
alert('Job saved successfully.');
document.getElementById('Salary').textContent = '';
document.getElementById('BudgetMin').value = '';
document.getElementById('conditionalFields').style.display = 'none';
})
.catch(error => {
console.error('Error:', error);
alert('Error: ' + error.message);
})
.finally(() => {
// Clear all fields in the form whether success or error
form.reset();
// Reset field borders to their default state
orderedFieldIds.forEach(id => {
const field = document.getElementById(id);
if (field) {
field.style.borderColor = 'initial'; // Reset to default border color
}
});
});
}
function validateDates() {
var startDate = new Date(document.getElementById("StartDate").value);
var closeDate = new Date(document.getElementById("CloseDate").value);
if (closeDate <= startDate) {
alert("Close Date must be greater than Start Date.");
document.getElementById("CloseDate").value = "";
}
}
function validateAmount() {
// Get values for minAmount and maxAmount fields
var minAmount = parseInt(document.getElementById("minAmount").value);
var maxAmount = parseInt(document.getElementById("maxAmount").value);
console.log(minAmount,maxAmount);
// Get input elements and error popup elements
var minAmountInput = document.getElementById("minAmount");
var maxAmountInput = document.getElementById("maxAmount");
var maxAmountErrorPopup = document.getElementById("maxAmountErrorPopup");
<!-- // Check if minAmount is a valid number-->
<!-- if (isNaN(minAmount) || minAmount <= 0) {-->
<!-- maxAmountErrorPopup.textContent = "Min amount must be greater than zero.";-->
<!-- maxAmountErrorPopup.style.display = "block";-->
<!-- maxAmountErrorPopup.style.borderColor = "red"; // Optionally, visually indicate error-->
<!-- maxAmountErrorPopup.focus();-->
<!-- return; // Prevent further validation-->
<!-- } else {-->
<!-- minAmountErrorPopup.style.display = "none"; // Hide error popup-->
<!-- minAmountInput.style.borderColor = ""; // Reset border color-->
<!-- }-->
<!-- // Check if maxAmount is a valid number-->
<!-- if (isNaN(maxAmount) || maxAmount <= 0) {-->
<!-- alert("Max amount must be greater than zero.");-->
<!-- maxAmountErrorPopup.textContent = "Max amount must be greater than zero.";-->
<!-- maxAmountErrorPopup.style.display = "block";-->
<!-- maxAmountInput.style.borderColor = "red"; // Optionally, visually indicate error-->
<!-- maxAmountInput.focus();-->
<!-- return; // Prevent further validation-->
<!-- } else {-->
<!-- maxAmountErrorPopup.style.display = "none"; // Hide error popup-->
<!-- maxAmountInput.style.borderColor = ""; // Reset border color-->
<!-- }-->
// Check if maxAmount is less than or equal to minAmount
if (maxAmount <= minAmount) {
alert("Max amount must be greater than Min amount.");
maxAmountErrorPopup.textContent = "Max amount must be greater than Min amount.";
maxAmountErrorPopup.style.display = "block";
maxAmountInput.style.borderColor = "red"; // Optionally, visually indicate error
maxAmountInput.focus();
return;
} else {
maxAmountErrorPopup.style.display = "none"; // Hide error popup
maxAmountInput.style.borderColor = ""; // Reset border color
}
}
// Attach the validation function to input and blur events for both fields
<!--document.getElementById("minAmount").addEventListener("input", validateAmount);-->
<!--document.getElementById("minAmount").addEventListener("blur", validateAmount);-->
document.getElementById("maxAmount").addEventListener("input", validateAmount);
document.getElementById("maxAmount").addEventListener("blur", validateAmount);
function searchJob() {
var input, filter, table, tr, i, txtValue;
input = document.getElementById("searchInput");
filter = input.value.toUpperCase();
table = document.querySelector("table");
tr = table.getElementsByTagName("tr");
for (i = 1; i < tr.length; i++) {
var found = false;
// Check Client Name (1st column)
var clientTd = tr[i].getElementsByTagName("td")[0];
if (clientTd) {
txtValue = clientTd.textContent || clientTd.innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
found = true;
}
}
// Check JobID (2nd column)
var jobIdTd = tr[i].getElementsByTagName("td")[1];
if (jobIdTd) {
txtValue = jobIdTd.textContent || jobIdTd.innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
found = true;
}
}
// Show or hide the row based on search results
tr[i].style.display = found ? "" : "none";
}
}
function validateExperience(input) {
// Convert the input value to a string and ensure only up to two digits
if (input.value.length > 2) {
input.value = input.value.slice(0, 2);
}
}
function limitToThreeDigits(input) {
// Convert the input value to a string and ensure only up to two digits
if (input.value.length > 3) {
input.value = input.value.slice(0, 3);
}
}
3 weeks ago
//Messages//
//Activesidebar//
function setActiveBox(element) {
// Remove the 'active' class from all sidebar options
const options = document.querySelectorAll('.sidebarOption');
options.forEach(option => option.classList.remove('sidebarOption__active'));
// Add the 'active' class to the clicked element
element.classList.add('sidebarOption__active');
}
function loadUserPage(url, userId) {
// Fetch and load the Messages page dynamically
fetch(`${url}?user_id=${userId}`)
.then((response) => {
if (!response.ok) {
throw new Error('Failed to load the Messages page.');
}
return response.text(); // Assuming it returns the full page HTML content
})
.then((data) => {
// Dynamically insert the fetched page content into #content
const contentContainer = document.getElementById('content');
if (contentContainer) {
contentContainer.innerHTML = data;
// After page content is loaded, automatically render the inbox
renderInbox(); // Automatically display the inbox
setActiveBox(document.getElementById('inboxButton')); // Set Inbox as active
HideMessageDetails(); // Hide any message details by default
} else {
console.error('Content container not found in DOM.');
}
})
.catch((error) => {
console.error('Error loading the Messages page:', error);
// Display an error in case of failure
const contentContainer = document.getElementById('content');
if (contentContainer) {
contentContainer.innerHTML =
'<p>Error loading Messages page. Please try again later.</p>';
}
});
}
<!--document.addEventListener('click', function(event) {-->
<!-- const searchKeyword = document.getElementById('toField')-->
<!-- if (!searchKeyword) return;-->
<!-- function handleInternalEmployees() {-->
<!-- const keyword = searchKeyword.value.trim();-->
<!-- console.log('keyword1:',keyword);-->
<!-- if (keyword === '') {-->
<!-- const autocompleteDropdown = document.getElementById('autocompleteDropdown');-->
<!-- autocompleteDropdown.innerHTML = '';-->
<!-- return;-->
<!-- }-->
<!-- getInternalEmployees();-->
<!-- }-->
<!-- function getInternalEmployees() {-->
<!-- const searchKeyword = document.getElementById('toField').value;-->
<!-- console.log('keyword2:',searchKeyword);-->
<!-- let xhr = new XMLHttpRequest();-->
<!-- xhr.open('GET', `/skyonnadmin/get_InternalEmployees/?toField=${searchKeyword}`, true);-->
<!-- xhr.onload = function() {-->
<!-- if (xhr.status === 200) {-->
<!-- filteredData = JSON.parse(xhr.responseText);-->
<!-- console.log(filteredData);-->
<!-- renderAutocompleteDropdown(filteredData)-->
<!-- } else {-->
<!-- console.error('Request failed. Status: ' + xhr.status);-->
<!-- }-->
<!-- };-->
<!-- xhr.send();-->
<!-- }-->
<!-- searchKeyword.addEventListener('input', handleInternalEmployees);-->
<!--});-->
<!-- function renderAutocompleteDropdown(data) {-->
<!-- const autocompleteDropdown = document.getElementById('autocompleteDropdown');-->
<!-- autocompleteDropdown.innerHTML = '';-->
<!-- console.log(data.employees.length);-->
<!-- if (data.employees.length === 0) {-->
<!-- return;-->
<!-- }-->
<!-- else {-->
<!-- data.employees.forEach((employee)=> {-->
<!-- const box = document.createElement('div')-->
<!-- box.className = 'autocomplete-box';-->
<!-- box.innerHTML = `-->
<!-- <div class="employee-name">${employee.FirstName} ${employee.LastName}</div>-->
<!-- <div class="employee-email">${employee.Email1 || employee.Email2}</div>-->
<!-- `;-->
<!-- box.textContent =`${employee.FirstName} ${employee.LastName} <${employee.Email1}>`-->
<!-- box.addEventListener('click', function() {-->
<!-- const toField = document.getElementById('toField');-->
<!-- toField.value = `${employee.Email1}`;-->
<!-- autocompleteDropdown.style.display = 'none';-->
<!-- })-->
<!--&lt;!&ndash; box.style.display = 'block'&ndash;&gt;-->
<!-- autocompleteDropdown.appendChild(box);-->
<!-- console.log(box.textContent)-->
<!-- });-->
<!-- console.log(autocompleteDropdown.style.display);-->
<!-- autocompleteDropdown.style.display = 'block';-->
<!-- }-->
<!-- }-->
2 months ago
11 months ago
</script>
</body>
</html>