363 lines
14 KiB
HTML
363 lines
14 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Custom Task Status Service Test</title>
|
|
<style>
|
|
body {
|
|
font-family: Arial, sans-serif;
|
|
max-width: 1200px;
|
|
margin: 20px 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);
|
|
}
|
|
h1 {
|
|
color: #333;
|
|
border-bottom: 2px solid #4CAF50;
|
|
padding-bottom: 10px;
|
|
}
|
|
.test-section {
|
|
margin: 20px 0;
|
|
padding: 15px;
|
|
background: #f9f9f9;
|
|
border-left: 4px solid #2196F3;
|
|
}
|
|
.test-section h2 {
|
|
margin-top: 0;
|
|
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;
|
|
}
|
|
.result {
|
|
margin-top: 10px;
|
|
padding: 10px;
|
|
background: white;
|
|
border: 1px solid #ddd;
|
|
border-radius: 4px;
|
|
white-space: pre-wrap;
|
|
font-family: monospace;
|
|
font-size: 12px;
|
|
}
|
|
.success {
|
|
color: #4CAF50;
|
|
font-weight: bold;
|
|
}
|
|
.error {
|
|
color: #f44336;
|
|
font-weight: bold;
|
|
}
|
|
.status-badge {
|
|
display: inline-block;
|
|
padding: 4px 12px;
|
|
border-radius: 4px;
|
|
margin: 2px;
|
|
color: white;
|
|
font-size: 12px;
|
|
}
|
|
.input-group {
|
|
margin: 10px 0;
|
|
}
|
|
.input-group label {
|
|
display: inline-block;
|
|
width: 150px;
|
|
font-weight: bold;
|
|
}
|
|
.input-group input {
|
|
padding: 5px;
|
|
border: 1px solid #ddd;
|
|
border-radius: 4px;
|
|
width: 200px;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<h1>🎨 Custom Task Status Service Test</h1>
|
|
<p>This page tests the custom task status service implementation.</p>
|
|
|
|
<div class="test-section">
|
|
<h2>Setup</h2>
|
|
<div class="input-group">
|
|
<label>Project ID:</label>
|
|
<input type="number" id="projectId" value="1">
|
|
</div>
|
|
<button onclick="login()">Login as Admin</button>
|
|
<div id="loginResult" class="result" style="display:none;"></div>
|
|
</div>
|
|
|
|
<div class="test-section">
|
|
<h2>1. Get All Statuses</h2>
|
|
<button onclick="getAllStatuses()">Get All Statuses</button>
|
|
<div id="getAllResult" class="result" style="display:none;"></div>
|
|
</div>
|
|
|
|
<div class="test-section">
|
|
<h2>2. Create Custom Status</h2>
|
|
<div class="input-group">
|
|
<label>Status Name:</label>
|
|
<input type="text" id="createName" value="Ready for Review">
|
|
</div>
|
|
<div class="input-group">
|
|
<label>Color (optional):</label>
|
|
<input type="text" id="createColor" value="#9333EA" placeholder="#RRGGBB">
|
|
</div>
|
|
<button onclick="createStatus()">Create Status</button>
|
|
<div id="createResult" class="result" style="display:none;"></div>
|
|
</div>
|
|
|
|
<div class="test-section">
|
|
<h2>3. Update Custom Status</h2>
|
|
<div class="input-group">
|
|
<label>Status ID:</label>
|
|
<input type="text" id="updateId" placeholder="Enter status ID">
|
|
</div>
|
|
<div class="input-group">
|
|
<label>New Name:</label>
|
|
<input type="text" id="updateName" placeholder="New name">
|
|
</div>
|
|
<div class="input-group">
|
|
<label>New Color:</label>
|
|
<input type="text" id="updateColor" placeholder="#RRGGBB">
|
|
</div>
|
|
<div class="input-group">
|
|
<label>Set as Default:</label>
|
|
<input type="checkbox" id="updateDefault">
|
|
</div>
|
|
<button onclick="updateStatus()">Update Status</button>
|
|
<div id="updateResult" class="result" style="display:none;"></div>
|
|
</div>
|
|
|
|
<div class="test-section">
|
|
<h2>4. Reorder Statuses</h2>
|
|
<p>Enter comma-separated status IDs in desired order:</p>
|
|
<div class="input-group">
|
|
<label>Status IDs:</label>
|
|
<input type="text" id="reorderIds" placeholder="id1,id2,id3" style="width: 400px;">
|
|
</div>
|
|
<button onclick="reorderStatuses()">Reorder Statuses</button>
|
|
<div id="reorderResult" class="result" style="display:none;"></div>
|
|
</div>
|
|
|
|
<div class="test-section">
|
|
<h2>5. Delete Custom Status</h2>
|
|
<div class="input-group">
|
|
<label>Status ID:</label>
|
|
<input type="text" id="deleteId" placeholder="Enter status ID">
|
|
</div>
|
|
<div class="input-group">
|
|
<label>Reassign To (optional):</label>
|
|
<input type="text" id="reassignId" placeholder="Status ID for reassignment">
|
|
</div>
|
|
<button onclick="deleteStatus()">Delete Status</button>
|
|
<div id="deleteResult" class="result" style="display:none;"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<script type="module">
|
|
import { customTaskStatusService } from './src/services/customTaskStatus.ts'
|
|
import { apiClient } from './src/services/api.ts'
|
|
|
|
let token = null
|
|
|
|
window.login = async function() {
|
|
const resultDiv = document.getElementById('loginResult')
|
|
resultDiv.style.display = 'block'
|
|
resultDiv.textContent = 'Logging in...'
|
|
|
|
try {
|
|
const response = await fetch('http://localhost:8000/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
|
|
localStorage.setItem('access_token', token)
|
|
resultDiv.innerHTML = '<span class="success">✅ Login successful!</span>'
|
|
} else {
|
|
const error = await response.text()
|
|
resultDiv.innerHTML = `<span class="error">❌ Login failed: ${error}</span>`
|
|
}
|
|
} catch (error) {
|
|
resultDiv.innerHTML = `<span class="error">❌ Error: ${error.message}</span>`
|
|
}
|
|
}
|
|
|
|
window.getAllStatuses = async function() {
|
|
const resultDiv = document.getElementById('getAllResult')
|
|
resultDiv.style.display = 'block'
|
|
resultDiv.textContent = 'Loading...'
|
|
|
|
try {
|
|
const projectId = parseInt(document.getElementById('projectId').value)
|
|
const data = await customTaskStatusService.getAllStatuses(projectId)
|
|
|
|
let output = '<span class="success">✅ Success!</span>\n\n'
|
|
output += `System Statuses (${data.system_statuses.length}):\n`
|
|
data.system_statuses.forEach(status => {
|
|
output += ` • ${status.name} (${status.id}) - ${status.color}\n`
|
|
})
|
|
|
|
output += `\nCustom Statuses (${data.statuses.length}):\n`
|
|
data.statuses.forEach(status => {
|
|
const defaultMark = status.is_default ? ' [DEFAULT]' : ''
|
|
output += ` • ${status.name} (${status.id}) - ${status.color} - Order: ${status.order}${defaultMark}\n`
|
|
})
|
|
|
|
output += `\nDefault Status ID: ${data.default_status_id}`
|
|
|
|
resultDiv.textContent = output
|
|
} catch (error) {
|
|
resultDiv.innerHTML = `<span class="error">❌ Error: ${error.message}</span>\n${JSON.stringify(error.response?.data, null, 2)}`
|
|
}
|
|
}
|
|
|
|
window.createStatus = async function() {
|
|
const resultDiv = document.getElementById('createResult')
|
|
resultDiv.style.display = 'block'
|
|
resultDiv.textContent = 'Creating...'
|
|
|
|
try {
|
|
const projectId = parseInt(document.getElementById('projectId').value)
|
|
const name = document.getElementById('createName').value
|
|
const color = document.getElementById('createColor').value
|
|
|
|
const statusData = { name }
|
|
if (color) {
|
|
statusData.color = color
|
|
}
|
|
|
|
const data = await customTaskStatusService.createStatus(projectId, statusData)
|
|
|
|
let output = '<span class="success">✅ Status created!</span>\n\n'
|
|
output += `Message: ${data.message}\n\n`
|
|
output += `Created Status:\n`
|
|
output += ` ID: ${data.status.id}\n`
|
|
output += ` Name: ${data.status.name}\n`
|
|
output += ` Color: ${data.status.color}\n`
|
|
output += ` Order: ${data.status.order}\n`
|
|
output += ` Is Default: ${data.status.is_default}\n`
|
|
|
|
resultDiv.textContent = output
|
|
} catch (error) {
|
|
resultDiv.innerHTML = `<span class="error">❌ Error: ${error.message}</span>\n${JSON.stringify(error.response?.data, null, 2)}`
|
|
}
|
|
}
|
|
|
|
window.updateStatus = async function() {
|
|
const resultDiv = document.getElementById('updateResult')
|
|
resultDiv.style.display = 'block'
|
|
resultDiv.textContent = 'Updating...'
|
|
|
|
try {
|
|
const projectId = parseInt(document.getElementById('projectId').value)
|
|
const statusId = document.getElementById('updateId').value
|
|
const name = document.getElementById('updateName').value
|
|
const color = document.getElementById('updateColor').value
|
|
const isDefault = document.getElementById('updateDefault').checked
|
|
|
|
const updateData = {}
|
|
if (name) updateData.name = name
|
|
if (color) updateData.color = color
|
|
if (isDefault) updateData.is_default = true
|
|
|
|
const data = await customTaskStatusService.updateStatus(projectId, statusId, updateData)
|
|
|
|
let output = '<span class="success">✅ Status updated!</span>\n\n'
|
|
output += `Message: ${data.message}\n\n`
|
|
output += `Updated Status:\n`
|
|
output += ` ID: ${data.status.id}\n`
|
|
output += ` Name: ${data.status.name}\n`
|
|
output += ` Color: ${data.status.color}\n`
|
|
output += ` Order: ${data.status.order}\n`
|
|
output += ` Is Default: ${data.status.is_default}\n`
|
|
|
|
resultDiv.textContent = output
|
|
} catch (error) {
|
|
resultDiv.innerHTML = `<span class="error">❌ Error: ${error.message}</span>\n${JSON.stringify(error.response?.data, null, 2)}`
|
|
}
|
|
}
|
|
|
|
window.reorderStatuses = async function() {
|
|
const resultDiv = document.getElementById('reorderResult')
|
|
resultDiv.style.display = 'block'
|
|
resultDiv.textContent = 'Reordering...'
|
|
|
|
try {
|
|
const projectId = parseInt(document.getElementById('projectId').value)
|
|
const idsString = document.getElementById('reorderIds').value
|
|
const statusIds = idsString.split(',').map(id => id.trim())
|
|
|
|
const data = await customTaskStatusService.reorderStatuses(projectId, { status_ids: statusIds })
|
|
|
|
let output = '<span class="success">✅ Statuses reordered!</span>\n\n'
|
|
output += `Message: ${data.message}\n\n`
|
|
output += `New Order:\n`
|
|
data.all_statuses.statuses.forEach((status, index) => {
|
|
output += ` ${index + 1}. ${status.name} (${status.id}) - Order: ${status.order}\n`
|
|
})
|
|
|
|
resultDiv.textContent = output
|
|
} catch (error) {
|
|
resultDiv.innerHTML = `<span class="error">❌ Error: ${error.message}</span>\n${JSON.stringify(error.response?.data, null, 2)}`
|
|
}
|
|
}
|
|
|
|
window.deleteStatus = async function() {
|
|
const resultDiv = document.getElementById('deleteResult')
|
|
resultDiv.style.display = 'block'
|
|
resultDiv.textContent = 'Deleting...'
|
|
|
|
try {
|
|
const projectId = parseInt(document.getElementById('projectId').value)
|
|
const statusId = document.getElementById('deleteId').value
|
|
const reassignId = document.getElementById('reassignId').value
|
|
|
|
const deleteData = reassignId ? { reassign_to_status_id: reassignId } : undefined
|
|
|
|
const data = await customTaskStatusService.deleteStatus(projectId, statusId, deleteData)
|
|
|
|
let output = '<span class="success">✅ Status deleted!</span>\n\n'
|
|
output += `Message: ${data.message}\n\n`
|
|
output += `Remaining Custom Statuses:\n`
|
|
data.all_statuses.statuses.forEach(status => {
|
|
output += ` • ${status.name} (${status.id})\n`
|
|
})
|
|
|
|
resultDiv.textContent = output
|
|
} catch (error) {
|
|
resultDiv.innerHTML = `<span class="error">❌ Error: ${error.message}</span>\n${JSON.stringify(error.response?.data, null, 2)}`
|
|
}
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|