80 lines
2.5 KiB
TypeScript
80 lines
2.5 KiB
TypeScript
import { Router, Request, Response } from 'express'
|
|
import path from 'path'
|
|
import fs from 'fs'
|
|
import { q, Model, ModelPdf, Category } from '../db/index'
|
|
import { geometryOutputPath } from '../services/stepConverter'
|
|
|
|
const UPLOADS_DIR = process.env.UPLOADS_DIR ?? path.join(process.cwd(), 'uploads')
|
|
|
|
const router = Router()
|
|
|
|
router.get('/view/:slug', (req: Request, res: Response) => {
|
|
const model = q<Model & { category_name: string | null }>(`
|
|
SELECT m.*, c.name AS category_name
|
|
FROM models m
|
|
LEFT JOIN categories c ON c.id = m.category_id
|
|
WHERE m.slug = ?
|
|
`).get(req.params.slug)
|
|
|
|
if (!model) {
|
|
res.status(404).render('error', { status: 404, message: 'Model not found.' })
|
|
return
|
|
}
|
|
|
|
if (!model.is_public && !(req.session as { isAdmin?: boolean }).isAdmin) {
|
|
res.status(403).render('error', { status: 403, message: 'This model is not publicly available.' })
|
|
return
|
|
}
|
|
|
|
const pdfs = q<ModelPdf>(`SELECT * FROM model_pdfs WHERE model_id = ? ORDER BY sort_order`).all(model.id)
|
|
const baseUrl = process.env.BASE_URL ?? `http://localhost:${process.env.PORT ?? 3000}`
|
|
|
|
// Determine whether pre-processed geometry is available for STEP/STP
|
|
let hasGeometry = false
|
|
if (model.file_type === 'step' || model.file_type === 'stp') {
|
|
const absPath = path.resolve(UPLOADS_DIR, model.file_path)
|
|
hasGeometry = fs.existsSync(geometryOutputPath(absPath))
|
|
}
|
|
|
|
res.render('viewer', {
|
|
model,
|
|
pdfs,
|
|
shareUrl: `${baseUrl}/view/${model.slug}`,
|
|
hasGeometry,
|
|
})
|
|
})
|
|
|
|
// ---- Public model index --------------------------------------------------
|
|
|
|
router.get('/', (_req: Request, res: Response) => {
|
|
// Fetch categories that have at least one public model, plus their models
|
|
const categories = q<Category & { model_count: number }>(`
|
|
SELECT c.*, COUNT(m.id) AS model_count
|
|
FROM categories c
|
|
INNER JOIN models m ON m.category_id = c.id AND m.is_public = 1
|
|
GROUP BY c.id
|
|
HAVING model_count > 0
|
|
ORDER BY c.sort_order, c.name
|
|
`).all()
|
|
|
|
// For each category, fetch its models
|
|
const categorised = categories.map(cat => ({
|
|
category: cat,
|
|
models: q<Model>(`
|
|
SELECT * FROM models
|
|
WHERE is_public = 1 AND category_id = ?
|
|
ORDER BY created_at DESC
|
|
`).all(cat.id),
|
|
}))
|
|
|
|
const uncategorized = q<Model>(`
|
|
SELECT * FROM models
|
|
WHERE is_public = 1 AND category_id IS NULL
|
|
ORDER BY created_at DESC
|
|
`).all()
|
|
|
|
res.render('index', { categorised, uncategorized })
|
|
})
|
|
|
|
export default router
|