feat(b5): M2b — légende des cinq types et double type pour les indécis
Deux chips maximum : le premier alimente submission_type, le second s'écrit en tête de description_user (« Type suggéré : X ou Y »), sans ALTER NocoDB. Le marqueur « Type : non précisé » n'est posé que sans aucun type (contrat worker/enrich.js inchangé). ?categorie= présélectionne un seul chip. Tests : 16/16. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UvxdoEGWjCTSEJDmraYW96
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
043e2e2348
commit
a1edcf3093
+44
-5
@@ -25,6 +25,20 @@ export const TYPES_SUGGERES_LABELS: Record<TypeSuggere, string> = {
|
||||
references: 'Références',
|
||||
}
|
||||
|
||||
/**
|
||||
* Légende courte sous les chips — définitions tirées des textes existants du site :
|
||||
* ecosysteme/jobs/outils/references reprennent la tête d'onglet (`TABS`, pages/proposer.vue)
|
||||
* et/ou la phrase de l'échelle qui pointe vers ce type (utils/echelles.ts) ; reseau reprend
|
||||
* la tête d'onglet « Réseau AEP » et les champs projet/lien de FormReseau.vue.
|
||||
*/
|
||||
export const TYPES_SUGGERES_HINTS: Record<TypeSuggere, string> = {
|
||||
ecosysteme: 'entraide, mutualisation',
|
||||
reseau: 'acteurs et projets AEP',
|
||||
jobs: 'offres, plateformes d\'emploi',
|
||||
outils: 'ressources, méthodes',
|
||||
references: 'bibliothèque, ouvrages',
|
||||
}
|
||||
|
||||
/** URL http(s) uniquement — un `ftp://` ou autre schéma est invalide. */
|
||||
const httpUrl = z
|
||||
.string()
|
||||
@@ -42,6 +56,8 @@ export const LibreSubmitSchema = z
|
||||
.or(z.literal(''))
|
||||
.transform((v) => v || undefined),
|
||||
type_suggere: z.enum(TYPES_SUGGERES).optional().or(z.literal('')).transform((v) => (v ? v : undefined)),
|
||||
// Deuxième chip optionnelle (B5-M2b) — indécis entre deux types.
|
||||
type_secondaire: z.enum(TYPES_SUGGERES).optional().or(z.literal('')).transform((v) => (v ? v : undefined)),
|
||||
// Honeypot anti-spam : champ caché, doit rester vide pour un humain.
|
||||
site_web: z.string().optional().or(z.literal('')),
|
||||
})
|
||||
@@ -49,6 +65,14 @@ export const LibreSubmitSchema = z
|
||||
message: 'Ajoute au moins un lien ou quelques mots.',
|
||||
path: ['texte'],
|
||||
})
|
||||
.refine((data) => !data.type_secondaire || !!data.type_suggere, {
|
||||
message: 'Choisis d\'abord un type principal.',
|
||||
path: ['type_secondaire'],
|
||||
})
|
||||
.refine((data) => !data.type_secondaire || data.type_secondaire !== data.type_suggere, {
|
||||
message: 'Le second type doit être différent du premier.',
|
||||
path: ['type_secondaire'],
|
||||
})
|
||||
|
||||
export type LibreSubmitInput = z.infer<typeof LibreSubmitSchema>
|
||||
|
||||
@@ -75,26 +99,41 @@ function nomSuggere(data: LibreSubmitInput): string {
|
||||
return `[à qualifier] ${base || fallback || 'sans titre'}`
|
||||
}
|
||||
|
||||
function descriptionAvecLiens(texte: string, liens: string[], typeNonPrecise: boolean): string {
|
||||
/**
|
||||
* `prefixLine` est soit le marqueur worker « Type : non précisé » (aucun type choisi),
|
||||
* soit la ligne « Type suggéré : X ou Y » (double type) — jamais les deux à la fois,
|
||||
* et toujours en toute première position quand présent (contrat worker/enrich.js:562).
|
||||
*/
|
||||
function descriptionAvecLiens(texte: string, liens: string[], prefixLine?: string): string {
|
||||
const parts: string[] = []
|
||||
if (typeNonPrecise) parts.push('Type : non précisé')
|
||||
if (prefixLine) parts.push(prefixLine)
|
||||
if (texte.trim()) parts.push(texte.trim())
|
||||
if (liens.length) parts.push(`Liens :\n${liens.join('\n')}`)
|
||||
return parts.join('\n\n')
|
||||
}
|
||||
|
||||
function ligneTypeSuggere(data: LibreSubmitInput): string | undefined {
|
||||
if (!data.type_secondaire) return undefined
|
||||
// Le schéma garantit type_suggere défini dès que type_secondaire l'est.
|
||||
return `Type suggéré : ${TYPES_SUGGERES_LABELS[data.type_suggere!]} ou ${TYPES_SUGGERES_LABELS[data.type_secondaire]}`
|
||||
}
|
||||
|
||||
/** Mapping vers la table orgas existante (submission_type ecosysteme/reseau/job/outil). */
|
||||
export function toOrgaPayload(data: LibreSubmitInput) {
|
||||
const typeNonPrecise = !data.type_suggere || data.type_suggere === 'references'
|
||||
const hasSecondaire = !!data.type_secondaire
|
||||
// Marqueur worker posé uniquement quand aucun type exploitable n'a été choisi du tout —
|
||||
// un double type ne le pose jamais (contrat worker/enrich.js:562).
|
||||
const typeNonPrecise = !hasSecondaire && (!data.type_suggere || data.type_suggere === 'references')
|
||||
const submissionType = data.type_suggere && data.type_suggere !== 'references'
|
||||
? TYPE_TO_SUBMISSION_TYPE[data.type_suggere]
|
||||
: 'ecosysteme'
|
||||
const prefixLine = typeNonPrecise ? 'Type : non précisé' : ligneTypeSuggere(data)
|
||||
|
||||
return {
|
||||
submission_type: submissionType,
|
||||
nom: nomSuggere(data),
|
||||
url: data.liens[0] || null,
|
||||
description_user: descriptionAvecLiens(data.texte, data.liens, typeNonPrecise),
|
||||
description_user: descriptionAvecLiens(data.texte, data.liens, prefixLine),
|
||||
submitted_by_email: data.submitted_by_email || null,
|
||||
moderation_status: 'pending' as const,
|
||||
ai_processed: false,
|
||||
@@ -109,7 +148,7 @@ export function toReferencePayload(data: LibreSubmitInput) {
|
||||
titre: nomSuggere(data),
|
||||
auteur: 'non précisé',
|
||||
url: data.liens[0] || null,
|
||||
description: descriptionAvecLiens(data.texte, data.liens, false),
|
||||
description: descriptionAvecLiens(data.texte, data.liens, ligneTypeSuggere(data)),
|
||||
pertinence_rag: null,
|
||||
hashtags: null,
|
||||
submitted_by_email: data.submitted_by_email || null,
|
||||
|
||||
Reference in New Issue
Block a user