Files
tinker_tickets/views/admin/CustomFieldsView.php

269 lines
13 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
// Admin view for managing custom fields
// Receives $customFields from controller
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Custom Fields - Admin</title>
<link rel="icon" type="image/png" href="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/images/favicon.png">
<link rel="stylesheet" href="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/css/dashboard.css">
<link rel="stylesheet" href="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/css/ticket.css">
<script>
window.CSRF_TOKEN = '<?php
require_once __DIR__ . '/../../middleware/CsrfMiddleware.php';
echo CsrfMiddleware::getToken();
?>';
</script>
</head>
<body>
<div class="user-header">
<div class="user-header-left">
<a href="/" class="back-link">← Dashboard</a>
<span style="margin-left: 1rem; color: var(--terminal-amber);">Admin: Custom Fields</span>
</div>
<div class="user-header-right">
<?php if (isset($GLOBALS['currentUser'])): ?>
<span class="user-name"><?php echo htmlspecialchars($GLOBALS['currentUser']['display_name'] ?? $GLOBALS['currentUser']['username']); ?></span>
<span class="admin-badge">Admin</span>
<?php endif; ?>
</div>
</div>
<div class="ascii-frame-outer" style="max-width: 1200px; margin: 2rem auto;">
<span class="bottom-left-corner">╚</span>
<span class="bottom-right-corner">╝</span>
<div class="ascii-section-header">Custom Fields Management</div>
<div class="ascii-content">
<div class="ascii-frame-inner">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem;">
<h2 style="margin: 0;">Custom Field Definitions</h2>
<button onclick="showCreateModal()" class="btn">+ New Field</button>
</div>
<table style="width: 100%;">
<thead>
<tr>
<th>Order</th>
<th>Field Name</th>
<th>Label</th>
<th>Type</th>
<th>Category</th>
<th>Required</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php if (empty($customFields)): ?>
<tr>
<td colspan="8" style="text-align: center; padding: 2rem; color: var(--terminal-green-dim);">
No custom fields defined.
</td>
</tr>
<?php else: ?>
<?php foreach ($customFields as $field): ?>
<tr>
<td><?php echo $field['display_order']; ?></td>
<td><code><?php echo htmlspecialchars($field['field_name']); ?></code></td>
<td><?php echo htmlspecialchars($field['field_label']); ?></td>
<td><?php echo ucfirst($field['field_type']); ?></td>
<td><?php echo htmlspecialchars($field['category'] ?? 'All'); ?></td>
<td><?php echo $field['is_required'] ? 'Yes' : 'No'; ?></td>
<td>
<span style="color: <?php echo $field['is_active'] ? 'var(--status-open)' : 'var(--status-closed)'; ?>;">
<?php echo $field['is_active'] ? 'Active' : 'Inactive'; ?>
</span>
</td>
<td>
<button onclick="editField(<?php echo $field['field_id']; ?>)" class="btn btn-small">Edit</button>
<button onclick="deleteField(<?php echo $field['field_id']; ?>)" class="btn btn-small btn-danger">Delete</button>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
<!-- Create/Edit Modal -->
<div class="settings-modal" id="fieldModal" style="display: none;">
<div class="settings-content" style="max-width: 500px;">
<div class="settings-header">
<h3 id="modalTitle">Create Custom Field</h3>
<button class="close-settings" onclick="closeModal()">×</button>
</div>
<form id="fieldForm" onsubmit="saveField(event)">
<input type="hidden" id="field_id" name="field_id">
<div class="settings-body">
<div class="setting-row">
<label for="field_name">Field Name * (internal)</label>
<input type="text" id="field_name" name="field_name" required pattern="[a-z_]+" placeholder="e.g., server_name">
</div>
<div class="setting-row">
<label for="field_label">Field Label * (display)</label>
<input type="text" id="field_label" name="field_label" required placeholder="e.g., Server Name">
</div>
<div class="setting-row">
<label for="field_type">Field Type *</label>
<select id="field_type" name="field_type" required onchange="toggleOptionsField()">
<option value="text">Text</option>
<option value="textarea">Text Area</option>
<option value="select">Dropdown (Select)</option>
<option value="checkbox">Checkbox</option>
<option value="date">Date</option>
<option value="number">Number</option>
</select>
</div>
<div class="setting-row" id="options_row" style="display: none;">
<label for="field_options">Options (one per line)</label>
<textarea id="field_options" name="field_options" rows="4" placeholder="Option 1&#10;Option 2&#10;Option 3"></textarea>
</div>
<div class="setting-row">
<label for="category">Category (empty = all)</label>
<select id="category" name="category">
<option value="">All Categories</option>
<option value="General">General</option>
<option value="Hardware">Hardware</option>
<option value="Software">Software</option>
<option value="Network">Network</option>
<option value="Security">Security</option>
</select>
</div>
<div class="setting-row">
<label for="display_order">Display Order</label>
<input type="number" id="display_order" name="display_order" value="0" min="0">
</div>
<div class="setting-row">
<label><input type="checkbox" id="is_required" name="is_required"> Required field</label>
</div>
<div class="setting-row">
<label><input type="checkbox" id="is_active" name="is_active" checked> Active</label>
</div>
</div>
<div class="settings-footer">
<button type="submit" class="btn btn-primary">Save</button>
<button type="button" class="btn btn-secondary" onclick="closeModal()">Cancel</button>
</div>
</form>
</div>
</div>
<script src="<?php echo $GLOBALS['config']['ASSETS_URL']; ?>/js/toast.js"></script>
<script>
function showCreateModal() {
document.getElementById('modalTitle').textContent = 'Create Custom Field';
document.getElementById('fieldForm').reset();
document.getElementById('field_id').value = '';
document.getElementById('is_active').checked = true;
toggleOptionsField();
document.getElementById('fieldModal').style.display = 'flex';
}
function closeModal() {
document.getElementById('fieldModal').style.display = 'none';
}
// Close modal on ESC key
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
closeModal();
}
});
// Close modal when clicking on backdrop (outside content)
document.getElementById('fieldModal').addEventListener('click', (e) => {
if (e.target.classList.contains('settings-modal')) {
closeModal();
}
});
function toggleOptionsField() {
const type = document.getElementById('field_type').value;
document.getElementById('options_row').style.display = type === 'select' ? 'block' : 'none';
}
function saveField(e) {
e.preventDefault();
const form = document.getElementById('fieldForm');
const data = {
field_id: document.getElementById('field_id').value,
field_name: document.getElementById('field_name').value,
field_label: document.getElementById('field_label').value,
field_type: document.getElementById('field_type').value,
category: document.getElementById('category').value || null,
display_order: parseInt(document.getElementById('display_order').value) || 0,
is_required: document.getElementById('is_required').checked ? 1 : 0,
is_active: document.getElementById('is_active').checked ? 1 : 0
};
if (data.field_type === 'select') {
const options = document.getElementById('field_options').value.split('\n').filter(o => o.trim());
data.field_options = { options: options };
}
const method = data.field_id ? 'PUT' : 'POST';
const url = '/api/custom_fields.php' + (data.field_id ? '?id=' + data.field_id : '');
fetch(url, {
method: method,
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': window.CSRF_TOKEN
},
body: JSON.stringify(data)
})
.then(r => r.json())
.then(result => {
if (result.success) {
window.location.reload();
} else {
toast.error(result.error || 'Failed to save');
}
});
}
function editField(id) {
fetch('/api/custom_fields.php?id=' + id)
.then(r => r.json())
.then(data => {
if (data.success && data.field) {
const f = data.field;
document.getElementById('field_id').value = f.field_id;
document.getElementById('field_name').value = f.field_name;
document.getElementById('field_label').value = f.field_label;
document.getElementById('field_type').value = f.field_type;
document.getElementById('category').value = f.category || '';
document.getElementById('display_order').value = f.display_order;
document.getElementById('is_required').checked = f.is_required == 1;
document.getElementById('is_active').checked = f.is_active == 1;
toggleOptionsField();
if (f.field_options && f.field_options.options) {
document.getElementById('field_options').value = f.field_options.options.join('\n');
}
document.getElementById('modalTitle').textContent = 'Edit Custom Field';
document.getElementById('fieldModal').style.display = 'flex';
}
});
}
function deleteField(id) {
if (!confirm('Delete this custom field? All values will be lost.')) return;
fetch('/api/custom_fields.php?id=' + id, {
method: 'DELETE',
headers: { 'X-CSRF-Token': window.CSRF_TOKEN }
})
.then(r => r.json())
.then(data => {
if (data.success) window.location.reload();
});
}
</script>
</body>
</html>