Temp user updates and several bug fixes
This commit is contained in:
@@ -358,6 +358,30 @@ function setupEventListeners() {
|
||||
if (clearUserBtn) {
|
||||
clearUserBtn.addEventListener('click', clearUserForm);
|
||||
}
|
||||
|
||||
// User type change listener
|
||||
const userTypeSelect = document.getElementById('user-type');
|
||||
if (userTypeSelect) {
|
||||
userTypeSelect.addEventListener('change', (e) => {
|
||||
const expirationGroup = document.getElementById('expiration-group');
|
||||
const isAdminCheckbox = document.getElementById('user-is-admin');
|
||||
|
||||
if (e.target.value === 'temp') {
|
||||
expirationGroup.style.display = 'block';
|
||||
isAdminCheckbox.checked = false;
|
||||
isAdminCheckbox.disabled = true;
|
||||
} else {
|
||||
expirationGroup.style.display = 'none';
|
||||
isAdminCheckbox.disabled = false;
|
||||
|
||||
if (e.target.value === 'admin') {
|
||||
isAdminCheckbox.checked = true;
|
||||
} else {
|
||||
isAdminCheckbox.checked = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Setup navigation between admin sections
|
||||
@@ -1282,16 +1306,34 @@ function displayUsers(users) {
|
||||
const createdDate = user.created_at || user['Created At'] || user.createdAt;
|
||||
const formattedDate = createdDate ? new Date(createdDate).toLocaleDateString() : 'N/A';
|
||||
const isAdmin = user.admin || user.Admin || false;
|
||||
const userType = user.UserType || user.userType || (isAdmin ? 'admin' : 'user');
|
||||
const userId = user.Id || user.id || user.ID;
|
||||
|
||||
// Handle expiration info
|
||||
let expirationInfo = '';
|
||||
if (user.ExpiresAt) {
|
||||
const expirationDate = new Date(user.ExpiresAt);
|
||||
const now = new Date();
|
||||
const daysUntilExpiration = Math.floor((expirationDate - now) / (1000 * 60 * 60 * 24));
|
||||
|
||||
if (daysUntilExpiration < 0) {
|
||||
expirationInfo = `<span class="expiration-info expiration-warning">Expired ${Math.abs(daysUntilExpiration)} days ago</span>`;
|
||||
} else if (daysUntilExpiration <= 3) {
|
||||
expirationInfo = `<span class="expiration-info expiration-warning">Expires in ${daysUntilExpiration} day${daysUntilExpiration !== 1 ? 's' : ''}</span>`;
|
||||
} else {
|
||||
expirationInfo = `<span class="expiration-info">Expires: ${expirationDate.toLocaleDateString()}</span>`;
|
||||
}
|
||||
}
|
||||
|
||||
return `
|
||||
<tr>
|
||||
<tr ${user.ExpiresAt && new Date(user.ExpiresAt) < new Date() ? 'class="expired"' : (user.ExpiresAt && new Date(user.ExpiresAt) - new Date() < 3 * 24 * 60 * 60 * 1000 ? 'class="expires-soon"' : '')}>
|
||||
<td data-label="Email">${escapeHtml(user.email || user.Email || 'N/A')}</td>
|
||||
<td data-label="Name">${escapeHtml(user.name || user.Name || 'N/A')}</td>
|
||||
<td data-label="Role">
|
||||
<span class="user-role ${isAdmin ? 'admin' : 'user'}">
|
||||
${isAdmin ? 'Admin' : 'User'}
|
||||
<span class="user-role ${userType}">
|
||||
${userType.charAt(0).toUpperCase() + userType.slice(1)}
|
||||
</span>
|
||||
${expirationInfo}
|
||||
</td>
|
||||
<td data-label="Created">${formattedDate}</td>
|
||||
<td data-label="Actions">
|
||||
@@ -1401,6 +1443,9 @@ async function createUser(e) {
|
||||
const email = document.getElementById('user-email').value.trim();
|
||||
const password = document.getElementById('user-password').value;
|
||||
const name = document.getElementById('user-name').value.trim();
|
||||
const userType = document.getElementById('user-type').value;
|
||||
const expireDays = userType === 'temp' ?
|
||||
parseInt(document.getElementById('user-expire-days').value) : null;
|
||||
const admin = document.getElementById('user-is-admin').checked;
|
||||
|
||||
if (!email || !password) {
|
||||
@@ -1413,18 +1458,27 @@ async function createUser(e) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (userType === 'temp' && (!expireDays || expireDays < 1 || expireDays > 365)) {
|
||||
showStatus('Expiration days must be between 1 and 365 for temporary users', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const userData = {
|
||||
email,
|
||||
password,
|
||||
name: name || '',
|
||||
isAdmin: userType === 'admin' || admin,
|
||||
userType,
|
||||
expireDays
|
||||
};
|
||||
|
||||
const response = await fetch('/api/users', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email,
|
||||
password,
|
||||
name: name || '',
|
||||
admin
|
||||
})
|
||||
body: JSON.stringify(userData)
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
@@ -1447,6 +1501,25 @@ function clearUserForm() {
|
||||
const form = document.getElementById('create-user-form');
|
||||
if (form) {
|
||||
form.reset();
|
||||
|
||||
// Reset user type to default
|
||||
const userTypeSelect = document.getElementById('user-type');
|
||||
if (userTypeSelect) {
|
||||
userTypeSelect.value = 'user';
|
||||
}
|
||||
|
||||
// Hide expiration group
|
||||
const expirationGroup = document.getElementById('expiration-group');
|
||||
if (expirationGroup) {
|
||||
expirationGroup.style.display = 'none';
|
||||
}
|
||||
|
||||
// Re-enable admin checkbox
|
||||
const isAdminCheckbox = document.getElementById('user-is-admin');
|
||||
if (isAdminCheckbox) {
|
||||
isAdminCheckbox.disabled = false;
|
||||
}
|
||||
|
||||
showStatus('User form cleared', 'info');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,24 +8,41 @@ export async function checkAuth() {
|
||||
const response = await fetch('/api/auth/check');
|
||||
const data = await response.json();
|
||||
|
||||
// Check if user has expired
|
||||
if (data.expired) {
|
||||
showStatus('Account has expired. Please contact an administrator.', 'error');
|
||||
setTimeout(() => {
|
||||
window.location.href = '/login.html?expired=true';
|
||||
}, 2000);
|
||||
throw new Error('Account expired');
|
||||
}
|
||||
|
||||
if (!data.authenticated) {
|
||||
window.location.href = '/login.html';
|
||||
throw new Error('Not authenticated');
|
||||
}
|
||||
|
||||
currentUser = data.user;
|
||||
currentUser.userType = data.user.userType || 'user'; // Ensure userType is set
|
||||
updateUserInterface();
|
||||
|
||||
} catch (error) {
|
||||
console.error('Auth check failed:', error);
|
||||
window.location.href = '/login.html';
|
||||
if (error.message !== 'Account expired') {
|
||||
window.location.href = '/login.html';
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export function updateUserInterface() {
|
||||
if (!currentUser) return;
|
||||
|
||||
|
||||
/* NEW – add a body class we can target with CSS */
|
||||
document.body.classList.toggle('temp-user', currentUser.userType === 'temp');
|
||||
document.body.classList.toggle('admin-user', currentUser.isAdmin === true);
|
||||
|
||||
// ----- existing code that manipulates DOM -----
|
||||
// Update user email in both desktop and mobile
|
||||
const userEmailElement = document.getElementById('user-email');
|
||||
const mobileUserEmailElement = document.getElementById('mobile-user-email');
|
||||
@@ -47,6 +64,52 @@ export function updateUserInterface() {
|
||||
}
|
||||
}
|
||||
|
||||
// Get all shifts links/buttons
|
||||
const shiftsLinks = document.querySelectorAll('a[href="/shifts.html"]');
|
||||
|
||||
if (currentUser.userType === 'temp') {
|
||||
// If user is temp, hide all shifts-related elements
|
||||
shiftsLinks.forEach(link => {
|
||||
const desktopButton = link.closest('.btn');
|
||||
const mobileItem = link.closest('.mobile-dropdown-item');
|
||||
|
||||
if (desktopButton) {
|
||||
desktopButton.classList.add('temp-restricted');
|
||||
}
|
||||
if (mobileItem) {
|
||||
mobileItem.classList.add('temp-restricted');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// If user is NOT temp, ensure all shifts-related elements are visible
|
||||
shiftsLinks.forEach(link => {
|
||||
const desktopButton = link.closest('.btn');
|
||||
const mobileItem = link.closest('.mobile-dropdown-item');
|
||||
|
||||
if (desktopButton) {
|
||||
desktopButton.classList.remove('temp-restricted');
|
||||
}
|
||||
if (mobileItem) {
|
||||
mobileItem.classList.remove('temp-restricted');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Add temp user indicator for temp users
|
||||
if (currentUser.userType === 'temp') {
|
||||
// Hide user profile links
|
||||
const userLinks = document.querySelectorAll('a[href="/user.html"]');
|
||||
userLinks.forEach(link => link.style.display = 'none');
|
||||
|
||||
// Add temp user indicator
|
||||
if (userEmailElement) {
|
||||
userEmailElement.innerHTML = `${currentUser.email} <span class="badge temp-badge">Temp</span>`;
|
||||
}
|
||||
if (mobileUserEmailElement) {
|
||||
mobileUserEmailElement.innerHTML = `${currentUser.email} <span class="badge temp-badge">Temp</span>`;
|
||||
}
|
||||
}
|
||||
|
||||
// Add admin link if user is admin
|
||||
if (currentUser.isAdmin) {
|
||||
addAdminLinks();
|
||||
|
||||
@@ -244,10 +244,12 @@ function createPopupContent(location) {
|
||||
data-location='${escapeHtml(JSON.stringify(location))}'>
|
||||
✏️ Edit
|
||||
</button>
|
||||
<button class="btn btn-primary btn-sm move-location-popup-btn"
|
||||
data-location='${escapeHtml(JSON.stringify(location))}'>
|
||||
📍 Move
|
||||
</button>
|
||||
${currentUser.userType !== 'temp' ? `
|
||||
<button class="btn btn-primary btn-sm move-location-popup-btn"
|
||||
data-location='${escapeHtml(JSON.stringify(location))}'>
|
||||
📍 Move
|
||||
</button>
|
||||
` : ''}
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
@@ -345,6 +347,16 @@ export function openEditForm(location) {
|
||||
document.getElementById('edit-location-lng').value = location.longitude || '';
|
||||
document.getElementById('edit-geo-location').value = location['Geo-Location'] || '';
|
||||
|
||||
// Show/hide delete button based on user type
|
||||
const deleteBtn = document.getElementById('delete-location-btn');
|
||||
if (deleteBtn) {
|
||||
if (currentUser?.userType === 'temp') {
|
||||
deleteBtn.style.display = 'none';
|
||||
} else {
|
||||
deleteBtn.style.display = '';
|
||||
}
|
||||
}
|
||||
|
||||
// Show edit footer
|
||||
document.getElementById('edit-footer').classList.remove('hidden');
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import { MkDocsSearch } from './mkdocs-search.js';
|
||||
import mapSearch from './map-search.js';
|
||||
import databaseSearch from './database-search.js';
|
||||
import { currentUser } from './auth.js';
|
||||
|
||||
export class UnifiedSearchManager {
|
||||
constructor(config = {}) {
|
||||
@@ -72,6 +73,14 @@ export class UnifiedSearchManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Hide database search option for temp users
|
||||
if (currentUser?.userType === 'temp') {
|
||||
const databaseModeBtn = container.querySelector('[data-mode="database"]');
|
||||
if (databaseModeBtn) {
|
||||
databaseModeBtn.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
this.setupEventListeners();
|
||||
this.updatePlaceholder();
|
||||
return true;
|
||||
@@ -187,6 +196,13 @@ export class UnifiedSearchManager {
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent database search for temp users
|
||||
if (currentUser?.userType === 'temp' && mode === 'database') {
|
||||
console.log('Database search not available for temporary users');
|
||||
this.showError('Database search is not available for temporary users');
|
||||
return;
|
||||
}
|
||||
|
||||
this.mode = mode;
|
||||
|
||||
// Update button states
|
||||
|
||||
Reference in New Issue
Block a user