Consolidated round management, AI filtering enhancements, MinIO storage restructure
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m45s
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m45s
- Fix STAGE_ACTIVE bug in assignment router (now ROUND_ACTIVE)
- Add evaluation form CRUD (getForm + upsertForm endpoints)
- Add advanceProjects mutation for manual project advancement
- Rewrite round detail page: 7-tab consolidated interface
- Add filtering rules UI with full CRUD (field-based, document check, AI screening)
- Add pageCount field to ProjectFile for document page limit filtering
- Enhance AI filtering: per-file page limits, category/region-aware guidelines
- Restructure MinIO paths: {ProjectName}/{RoundName}/{timestamp}-{file}
- Update dashboard and pool page links from /admin/competitions to /admin/rounds
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -119,14 +119,39 @@ export async function deleteObject(
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a unique object key for a project file
|
||||
* Sanitize a name for use as a MinIO path segment.
|
||||
* Removes special characters, replaces spaces with underscores, limits length.
|
||||
*/
|
||||
export function generateObjectKey(
|
||||
projectId: string,
|
||||
fileName: string
|
||||
): string {
|
||||
const timestamp = Date.now()
|
||||
const sanitizedName = fileName.replace(/[^a-zA-Z0-9.-]/g, '_')
|
||||
return `projects/${projectId}/${timestamp}-${sanitizedName}`
|
||||
function sanitizePath(name: string): string {
|
||||
return (
|
||||
name
|
||||
.trim()
|
||||
.replace(/[^a-zA-Z0-9\-_ ]/g, '')
|
||||
.replace(/\s+/g, '_')
|
||||
.substring(0, 100) || 'unnamed'
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a unique object key for a project file.
|
||||
*
|
||||
* Structure: {ProjectName}/{RoundName}/{timestamp}-{fileName}
|
||||
* - projectName: human-readable project title (sanitized)
|
||||
* - roundName: round name for submission context (sanitized), defaults to "general"
|
||||
* - fileName: original file name (sanitized)
|
||||
*
|
||||
* Existing files with old-style keys (projects/{id}/...) are unaffected
|
||||
* because retrieval uses the objectKey stored in the database.
|
||||
*/
|
||||
export function generateObjectKey(
|
||||
projectName: string,
|
||||
fileName: string,
|
||||
roundName?: string
|
||||
): string {
|
||||
const timestamp = Date.now()
|
||||
const sanitizedProject = sanitizePath(projectName)
|
||||
const sanitizedRound = roundName ? sanitizePath(roundName) : 'general'
|
||||
const sanitizedFile = fileName.replace(/[^a-zA-Z0-9.-]/g, '_')
|
||||
return `${sanitizedProject}/${sanitizedRound}/${timestamp}-${sanitizedFile}`
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user