Init Repo
This commit is contained in:
@@ -0,0 +1,364 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Test Custom Task Columns in Asset Browser</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.container {
|
||||
background: white;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
h1 {
|
||||
color: #333;
|
||||
border-bottom: 2px solid #4CAF50;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
h2 {
|
||||
color: #555;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.test-section {
|
||||
margin: 20px 0;
|
||||
padding: 15px;
|
||||
background: #f9f9f9;
|
||||
border-left: 4px solid #4CAF50;
|
||||
}
|
||||
.success {
|
||||
color: #4CAF50;
|
||||
font-weight: bold;
|
||||
}
|
||||
.error {
|
||||
color: #f44336;
|
||||
font-weight: bold;
|
||||
}
|
||||
.info {
|
||||
color: #2196F3;
|
||||
}
|
||||
button {
|
||||
background-color: #4CAF50;
|
||||
color: white;
|
||||
padding: 10px 20px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
margin: 5px;
|
||||
}
|
||||
button:hover {
|
||||
background-color: #45a049;
|
||||
}
|
||||
button:disabled {
|
||||
background-color: #cccccc;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 10px 0;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
}
|
||||
th {
|
||||
background-color: #4CAF50;
|
||||
color: white;
|
||||
}
|
||||
tr:nth-child(even) {
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
.column-toggle {
|
||||
margin: 10px 0;
|
||||
padding: 10px;
|
||||
background: #e3f2fd;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.column-toggle label {
|
||||
display: inline-block;
|
||||
margin-right: 15px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>🎬 Custom Task Columns Test</h1>
|
||||
<p>This page tests the custom task type columns in the asset browser</p>
|
||||
|
||||
<div class="test-section">
|
||||
<h2>Authentication</h2>
|
||||
<div id="auth-status">Not logged in</div>
|
||||
<button onclick="login()">Login as Admin</button>
|
||||
</div>
|
||||
|
||||
<div class="test-section">
|
||||
<h2>Test 1: Load Project Custom Task Types</h2>
|
||||
<button onclick="loadCustomTaskTypes()" id="test1-btn" disabled>Load Custom Task Types</button>
|
||||
<div id="test1-results"></div>
|
||||
</div>
|
||||
|
||||
<div class="test-section">
|
||||
<h2>Test 2: Column Visibility Control</h2>
|
||||
<div class="column-toggle" id="column-controls">
|
||||
<button onclick="toggleAllTaskColumns()" id="toggle-all-btn" disabled>
|
||||
Show/Hide All Task Columns
|
||||
</button>
|
||||
<div id="column-checkboxes" style="margin-top: 10px;"></div>
|
||||
</div>
|
||||
<div id="test2-results"></div>
|
||||
</div>
|
||||
|
||||
<div class="test-section">
|
||||
<h2>Test 3: Asset Table with Custom Columns</h2>
|
||||
<button onclick="loadAssetsWithCustomColumns()" id="test3-btn" disabled>Load Assets</button>
|
||||
<div id="test3-results"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const API_BASE = 'http://localhost:8000';
|
||||
let token = null;
|
||||
let projectId = null;
|
||||
let customTaskTypes = [];
|
||||
let visibleColumns = {
|
||||
name: true,
|
||||
category: true,
|
||||
status: true,
|
||||
modeling: true,
|
||||
surfacing: true,
|
||||
rigging: true,
|
||||
description: true
|
||||
};
|
||||
let savedTaskColumnStates = {};
|
||||
|
||||
async function login() {
|
||||
try {
|
||||
const response = await fetch(`${API_BASE}/auth/login`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
email: 'admin@vfx.com',
|
||||
password: 'admin123'
|
||||
})
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
token = data.access_token;
|
||||
document.getElementById('auth-status').innerHTML = '<span class="success">✅ Logged in successfully</span>';
|
||||
|
||||
// Get project
|
||||
await getProject();
|
||||
|
||||
// Enable test buttons
|
||||
document.getElementById('test1-btn').disabled = false;
|
||||
document.getElementById('test2-btn').disabled = false;
|
||||
document.getElementById('test3-btn').disabled = false;
|
||||
document.getElementById('toggle-all-btn').disabled = false;
|
||||
} else {
|
||||
document.getElementById('auth-status').innerHTML = '<span class="error">❌ Login failed</span>';
|
||||
}
|
||||
} catch (error) {
|
||||
document.getElementById('auth-status').innerHTML = `<span class="error">❌ Error: ${error.message}</span>`;
|
||||
}
|
||||
}
|
||||
|
||||
async function getProject() {
|
||||
const response = await fetch(`${API_BASE}/projects/`, {
|
||||
headers: { 'Authorization': `Bearer ${token}` }
|
||||
});
|
||||
const projects = await response.json();
|
||||
if (projects.length > 0) {
|
||||
projectId = projects[0].id;
|
||||
document.getElementById('auth-status').innerHTML += `<br><span class="info">Using project: ${projects[0].name} (ID: ${projectId})</span>`;
|
||||
}
|
||||
}
|
||||
|
||||
async function loadCustomTaskTypes() {
|
||||
const resultsDiv = document.getElementById('test1-results');
|
||||
resultsDiv.innerHTML = '<p>Loading custom task types...</p>';
|
||||
|
||||
try {
|
||||
const response = await fetch(`${API_BASE}/projects/${projectId}`, {
|
||||
headers: { 'Authorization': `Bearer ${token}` }
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const project = await response.json();
|
||||
customTaskTypes = project.custom_asset_task_types || [];
|
||||
|
||||
let results = `<p class="success">✅ Loaded ${customTaskTypes.length} custom task types</p>`;
|
||||
|
||||
if (customTaskTypes.length > 0) {
|
||||
results += '<p><strong>Custom Task Types:</strong></p><ul>';
|
||||
customTaskTypes.forEach(type => {
|
||||
results += `<li>${type}</li>`;
|
||||
// Initialize visibility for custom types
|
||||
if (!(type in visibleColumns)) {
|
||||
visibleColumns[type] = true;
|
||||
}
|
||||
});
|
||||
results += '</ul>';
|
||||
} else {
|
||||
results += '<p class="info">No custom task types defined for this project</p>';
|
||||
}
|
||||
|
||||
resultsDiv.innerHTML = results;
|
||||
updateColumnCheckboxes();
|
||||
} else {
|
||||
resultsDiv.innerHTML = '<p class="error">❌ Failed to load project</p>';
|
||||
}
|
||||
} catch (error) {
|
||||
resultsDiv.innerHTML = `<p class="error">❌ Error: ${error.message}</p>`;
|
||||
}
|
||||
}
|
||||
|
||||
function updateColumnCheckboxes() {
|
||||
const checkboxesDiv = document.getElementById('column-checkboxes');
|
||||
const standardTypes = ['modeling', 'surfacing', 'rigging'];
|
||||
const allTypes = [...standardTypes, ...customTaskTypes];
|
||||
|
||||
let html = '<strong>Task Columns:</strong><br>';
|
||||
allTypes.forEach(type => {
|
||||
const checked = visibleColumns[type] ? 'checked' : '';
|
||||
const label = type.split('_').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');
|
||||
html += `
|
||||
<label>
|
||||
<input type="checkbox" ${checked} onchange="toggleColumn('${type}')" />
|
||||
${label}
|
||||
</label>
|
||||
`;
|
||||
});
|
||||
|
||||
checkboxesDiv.innerHTML = html;
|
||||
}
|
||||
|
||||
function toggleColumn(column) {
|
||||
visibleColumns[column] = !visibleColumns[column];
|
||||
updateColumnCheckboxes();
|
||||
|
||||
const resultsDiv = document.getElementById('test2-results');
|
||||
resultsDiv.innerHTML = `<p class="info">Column "${column}" is now ${visibleColumns[column] ? 'visible' : 'hidden'}</p>`;
|
||||
}
|
||||
|
||||
function toggleAllTaskColumns() {
|
||||
const standardTypes = ['modeling', 'surfacing', 'rigging'];
|
||||
const allTypes = [...standardTypes, ...customTaskTypes];
|
||||
|
||||
// Check if all are visible
|
||||
const allVisible = allTypes.every(type => visibleColumns[type]);
|
||||
|
||||
if (allVisible) {
|
||||
// Hide all and save states
|
||||
savedTaskColumnStates = {};
|
||||
allTypes.forEach(type => {
|
||||
savedTaskColumnStates[type] = visibleColumns[type];
|
||||
visibleColumns[type] = false;
|
||||
});
|
||||
} else {
|
||||
// Restore saved states or show all
|
||||
allTypes.forEach(type => {
|
||||
if (type in savedTaskColumnStates) {
|
||||
visibleColumns[type] = savedTaskColumnStates[type];
|
||||
} else {
|
||||
visibleColumns[type] = true;
|
||||
}
|
||||
});
|
||||
savedTaskColumnStates = {};
|
||||
}
|
||||
|
||||
updateColumnCheckboxes();
|
||||
|
||||
const resultsDiv = document.getElementById('test2-results');
|
||||
resultsDiv.innerHTML = `<p class="success">✅ ${allVisible ? 'Hidden' : 'Shown'} all task columns</p>`;
|
||||
}
|
||||
|
||||
async function loadAssetsWithCustomColumns() {
|
||||
const resultsDiv = document.getElementById('test3-results');
|
||||
resultsDiv.innerHTML = '<p>Loading assets...</p>';
|
||||
|
||||
try {
|
||||
const response = await fetch(`${API_BASE}/assets/?project_id=${projectId}`, {
|
||||
headers: { 'Authorization': `Bearer ${token}` }
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const assets = await response.json();
|
||||
|
||||
if (assets.length === 0) {
|
||||
resultsDiv.innerHTML = '<p class="info">No assets found</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
// Build table with dynamic columns
|
||||
const standardTypes = ['modeling', 'surfacing', 'rigging'];
|
||||
const allTaskTypes = [...standardTypes, ...customTaskTypes];
|
||||
|
||||
let html = `<p class="success">✅ Loaded ${assets.length} assets</p>`;
|
||||
html += '<table><thead><tr>';
|
||||
|
||||
// Basic columns
|
||||
if (visibleColumns.name) html += '<th>Name</th>';
|
||||
if (visibleColumns.category) html += '<th>Category</th>';
|
||||
if (visibleColumns.status) html += '<th>Status</th>';
|
||||
|
||||
// Task columns
|
||||
allTaskTypes.forEach(type => {
|
||||
if (visibleColumns[type]) {
|
||||
const label = type.split('_').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');
|
||||
html += `<th>${label}</th>`;
|
||||
}
|
||||
});
|
||||
|
||||
if (visibleColumns.description) html += '<th>Description</th>';
|
||||
|
||||
html += '</tr></thead><tbody>';
|
||||
|
||||
// Asset rows
|
||||
assets.slice(0, 10).forEach(asset => {
|
||||
html += '<tr>';
|
||||
|
||||
if (visibleColumns.name) html += `<td>${asset.name}</td>`;
|
||||
if (visibleColumns.category) html += `<td>${asset.category}</td>`;
|
||||
if (visibleColumns.status) html += `<td>${asset.status}</td>`;
|
||||
|
||||
// Task status cells
|
||||
allTaskTypes.forEach(type => {
|
||||
if (visibleColumns[type]) {
|
||||
const status = asset.task_status?.[type] || 'not_started';
|
||||
html += `<td>${status}</td>`;
|
||||
}
|
||||
});
|
||||
|
||||
if (visibleColumns.description) html += `<td>${asset.description || '-'}</td>`;
|
||||
|
||||
html += '</tr>';
|
||||
});
|
||||
|
||||
html += '</tbody></table>';
|
||||
|
||||
if (assets.length > 10) {
|
||||
html += `<p class="info">Showing first 10 of ${assets.length} assets</p>`;
|
||||
}
|
||||
|
||||
resultsDiv.innerHTML = html;
|
||||
} else {
|
||||
resultsDiv.innerHTML = '<p class="error">❌ Failed to load assets</p>';
|
||||
}
|
||||
} catch (error) {
|
||||
resultsDiv.innerHTML = `<p class="error">❌ Error: ${error.message}</p>`;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user