mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-08-10 15:21:22 +02:00
fix: unify CSV import/export columns, fix import JS error, fix createThesis VALUES
- Fix createThesis SQL: extra ? placeholder in VALUES (27 values for 26 columns) - Add createThesis integration tests to catch column/value mismatches - Add CSV_COLUMNS as single source of truth in ExportController, deriving csvHeaders() and positional fallback from it - Add missing columns to export query + CSV: duration_pages, duration_minutes, has_annexes, license_custom, contact_visible, objet - Add missing columns to import INSERT: license_id, license_custom, cc2r, exemplaire_baiu, exemplaire_erg, objet, contact_visible, duration_pages, duration_minutes, has_annexes - Resolve license name → license_id during import - Fix XamxamInitFilePonds: add file-upload-filepond.js to admin-entry.js so FilePond initialization code is available on the admin list page - Add FilePond vendor CSS to admin.min.css bundle (import dialog styling) - Generate .admin-file-hint from csvHeaders() instead of hardcoded stale list - Use positional fallback from CSV_COLUMNS for import cell parsing
This commit is contained in:
@@ -250,6 +250,59 @@ class ExportController
|
||||
/**
|
||||
* Column headers matching the import format.
|
||||
*/
|
||||
/**
|
||||
* Single source of truth for CSV column definitions.
|
||||
* Each entry: [header_label, field_key, import_search_key]
|
||||
*
|
||||
* field_key = key in the SELECT row and export data array
|
||||
* import_key = lowercase token used to match header rows during import
|
||||
*/
|
||||
public const CSV_COLUMNS = [
|
||||
['Identifiant', 'identifier', 'identifiant'],
|
||||
['Titre', 'title', 'titre'],
|
||||
['Sous-titre', 'subtitle', 'sous-titre'],
|
||||
['Auteur·ice(s)', 'authors', 'auteur'],
|
||||
['Contact', 'contact', 'contact'],
|
||||
['Promoteur·ice(s) interne', 'promoteurs_internes', 'promoteur'],
|
||||
['Lecteur·ice(s) interne', 'lecteurs_internes', 'lecteur'],
|
||||
['Lecteur·ice(s) externe', 'lecteurs_externes', 'externe'],
|
||||
['Promoteur·ice(s) université', 'promoteurs_ulb', 'ulb'],
|
||||
['Format(s)', 'formats', 'format'],
|
||||
['Année', 'year', 'année'],
|
||||
['AP', 'ap_program', 'ap'],
|
||||
['Orientation', 'orientation', 'orientation'],
|
||||
['Finalité', 'finality', 'finalité'],
|
||||
['Mots-clés', 'keywords', 'mots-clés'],
|
||||
['Synopsis', 'synopsis', 'synopsis'],
|
||||
['Contexte', 'context', 'contexte'],
|
||||
['Remarques', 'remarks', 'remarques'],
|
||||
['Langue', 'languages', 'langue'],
|
||||
['Autorisation', 'access_type', 'autorisation'],
|
||||
['Licence', 'license', 'licence'],
|
||||
['Points sur 20', 'jury_points', 'points'],
|
||||
['Lien BAIU', 'baiu_link', 'lien baiu'],
|
||||
['CC2r', 'cc2r', 'cc2r'],
|
||||
['Exemplaire BAIU', 'exemplaire_baiu', 'exemplaire'],
|
||||
['Exemplaire ERG', 'exemplaire_erg', 'exemplaire-erg'],
|
||||
['Pages', 'duration_pages', 'pages'],
|
||||
['Durée (minutes)', 'duration_minutes', 'durée'],
|
||||
['Annexes', 'has_annexes', 'annexes'],
|
||||
['Licence personnalisée', 'license_custom', 'licence-perso'],
|
||||
['Contact visible', 'contact_visible', 'contact-visible'],
|
||||
['Objet', 'objet', 'objet'],
|
||||
];
|
||||
|
||||
/**
|
||||
* Derived from CSV_COLUMNS for backward compatibility.
|
||||
*/
|
||||
public static function csvHeaders(): array
|
||||
{
|
||||
return array_column(self::CSV_COLUMNS, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use csvHeaders() instead.
|
||||
*/
|
||||
public const CSV_HEADERS = [
|
||||
'Identifiant',
|
||||
'Titre',
|
||||
@@ -277,6 +330,12 @@ class ExportController
|
||||
'CC2r',
|
||||
'Exemplaire BAIU',
|
||||
'Exemplaire ERG',
|
||||
'Pages',
|
||||
'Durée (minutes)',
|
||||
'Annexes',
|
||||
'Licence personnalisée',
|
||||
'Contact visible',
|
||||
'Objet',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -396,6 +455,12 @@ class ExportController
|
||||
!empty($t['cc2r']) ? 'Oui' : 'Non',
|
||||
!empty($t['exemplaire_baiu']) ? 'Oui' : 'Non',
|
||||
!empty($t['exemplaire_erg']) ? 'Oui' : 'Non',
|
||||
isset($t['duration_pages']) && $t['duration_pages'] !== null ? (string) $t['duration_pages'] : '',
|
||||
isset($t['duration_minutes']) && $t['duration_minutes'] !== null ? (string) $t['duration_minutes'] : '',
|
||||
!empty($t['has_annexes']) ? 'Oui' : 'Non',
|
||||
$t['license_custom'] ?? '',
|
||||
$t['contact_visible'] ?? '',
|
||||
$t['objet'] ?? '',
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -2266,7 +2266,7 @@ class Database
|
||||
duration_pages, duration_minutes,
|
||||
has_annexes,
|
||||
submitted_at
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, "draft", ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, "draft", ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
|
||||
');
|
||||
|
||||
$validObjet = ['tfe', 'thèse', 'frart'];
|
||||
@@ -2696,7 +2696,13 @@ class Database
|
||||
t.baiu_link,
|
||||
t.exemplaire_baiu,
|
||||
t.exemplaire_erg,
|
||||
t.cc2r
|
||||
t.cc2r,
|
||||
t.license_custom,
|
||||
t.contact_visible,
|
||||
t.duration_pages,
|
||||
t.duration_minutes,
|
||||
t.has_annexes,
|
||||
t.objet
|
||||
FROM theses t
|
||||
LEFT JOIN orientations o ON t.orientation_id = o.id
|
||||
LEFT JOIN ap_programs ap ON t.ap_program_id = ap.id
|
||||
|
||||
Reference in New Issue
Block a user