auto-reload for admin + auto validation for all using python
This commit is contained in:
@@ -7,6 +7,7 @@ import { apiService, errorHelpers } from '@/services/apiService'
|
||||
import { usePuzzlesStore } from '@/stores/puzzles'
|
||||
import { useSubmissionsStore } from '@/stores/submissions'
|
||||
import type { SteamCollection, PuzzleResponse, UserInfo } from '@/types'
|
||||
import { useCountdown } from '@vueuse/core'
|
||||
|
||||
const props = defineProps<{collectionTitle: string, collectionUrl: string, collectionDescription: string}>()
|
||||
|
||||
@@ -19,8 +20,6 @@ const userInfo = ref<UserInfo | null>(null)
|
||||
const isLoading = ref(true)
|
||||
const error = ref<string>('')
|
||||
|
||||
// Mock data removed - using API data only
|
||||
|
||||
// Computed properties
|
||||
const isSuperuser = computed(() => {
|
||||
return userInfo.value?.is_superuser || false
|
||||
@@ -42,7 +41,7 @@ const responsesByPuzzle = computed(() => {
|
||||
return grouped
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
async function initialize() {
|
||||
try {
|
||||
isLoading.value = true
|
||||
error.value = ''
|
||||
@@ -78,6 +77,20 @@ onMounted(async () => {
|
||||
isLoading.value = false
|
||||
console.log('Loading state set to false')
|
||||
}
|
||||
|
||||
if (userInfo.value.is_superuser) {
|
||||
start()
|
||||
}
|
||||
}
|
||||
|
||||
const { remaining, start } = useCountdown(60, {
|
||||
onComplete() {
|
||||
initialize()
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
await initialize()
|
||||
})
|
||||
|
||||
const handleSubmission = async (submissionData: {
|
||||
@@ -165,6 +178,15 @@ const reloadPage = () => {
|
||||
<!-- Main Content -->
|
||||
<div class="container mx-auto px-4 py-8">
|
||||
<!-- Loading State -->
|
||||
<div v-if="userInfo?.is_superuser" class="flex justify-center">
|
||||
<div class="text-center">
|
||||
<p class="mb-6 text-base-content/70">
|
||||
<span class="loading loading-spinner loading-lg"></span>
|
||||
Auto reload page in {{ remaining }} seconds ...
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="isLoading" class="flex justify-center items-center min-h-[400px]">
|
||||
<div class="text-center">
|
||||
<span class="loading loading-spinner loading-lg"></span>
|
||||
|
||||
@@ -25,6 +25,11 @@
|
||||
<div class="stat-value text-success">{{ Math.round(stats.validation_rate * 100) }}%</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-sm btn-primary" @click="autoValidationResponse">
|
||||
<i class="mdi mdi-check-circle mr-1"></i>
|
||||
Auto validation for all responses
|
||||
</button>
|
||||
|
||||
<!-- Responses Needing Validation -->
|
||||
<div v-if="responsesNeedingValidation.length > 0">
|
||||
@@ -268,6 +273,23 @@ const loadData = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
const autoValidationResponse = async () => {
|
||||
for (const response of Array.from(responsesNeedingValidation.value)) {
|
||||
const {data, error} = await apiService.autoValidateResponses(response.id)
|
||||
|
||||
if (data && !data.needs_manual_validation) {
|
||||
// Remove from validation list
|
||||
responsesNeedingValidation.value = responsesNeedingValidation.value.filter(
|
||||
r => r.id !== response.id
|
||||
)
|
||||
stats.value.needs_validation -= 1
|
||||
|
||||
} else if (error) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const openValidationModal = (response: PuzzleResponse) => {
|
||||
validationModal.value.response = response
|
||||
validationModal.value.data = {
|
||||
|
||||
@@ -158,6 +158,12 @@ export class ApiService {
|
||||
})
|
||||
}
|
||||
|
||||
async autoValidateResponses(responseId: number): Promise<ApiResponse<PuzzleResponse>> {
|
||||
return this.request<PuzzleResponse>(`/submissions/responses/${responseId}/validate/auto`, {
|
||||
method: 'PUT',
|
||||
})
|
||||
}
|
||||
|
||||
async getResponsesNeedingValidation(): Promise<ApiResponse<PuzzleResponse[]>> {
|
||||
return this.request<PuzzleResponse[]>('/submissions/responses/needs-validation')
|
||||
}
|
||||
@@ -226,7 +232,7 @@ export const puzzleHelpers = {
|
||||
|
||||
export const submissionHelpers = {
|
||||
async createFromFiles(
|
||||
files: SubmissionFile[],
|
||||
files: SubmissionFile[],
|
||||
puzzles: SteamCollectionItem[],
|
||||
notes?: string,
|
||||
manualValidationRequested?: boolean
|
||||
@@ -240,7 +246,7 @@ export const submissionHelpers = {
|
||||
files.forEach(file => {
|
||||
// Use manual puzzle selection if available, otherwise fall back to OCR
|
||||
const puzzleName = file.manualPuzzleSelection || file.ocrData?.puzzle
|
||||
|
||||
|
||||
if (puzzleName) {
|
||||
if (!responsesByPuzzle[puzzleName]) {
|
||||
responsesByPuzzle[puzzleName] = {
|
||||
@@ -290,10 +296,10 @@ export const submissionHelpers = {
|
||||
// Extract actual File objects for upload
|
||||
const fileObjects = files.map(f => f.file)
|
||||
|
||||
return apiService.createSubmission({
|
||||
notes,
|
||||
return apiService.createSubmission({
|
||||
notes,
|
||||
manual_validation_requested: manualValidationRequested,
|
||||
responses
|
||||
responses
|
||||
}, fileObjects)
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user