feat: add CSV export button in panel for contact database
All checks were successful
Deploy Production / Deploy to Production (push) Successful in 21s

- Plugin csv-export: authenticated route /wg-export/contacts generates
  CSV with UTF-8 BOM, semicolon separator, white-paper titles resolved
- Panel section with k-button wired to the route, index.css for spacing
- white-papers.yml dataTab converted to sections to host the custom section
- Filename format: YYMMDD-contacts.csv

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
isUnknown 2026-06-01 14:00:23 +02:00
parent fb29a8fb98
commit effe6ec547
4 changed files with 130 additions and 54 deletions

View file

@ -48,62 +48,68 @@ tabs:
dataTab:
label: Contacts
icon: chart
fields:
contactDatabase:
label: Ont téléchargé un livre blanc
type: structure
translate: false
columns:
firstName:
label: Prénom
width: 1/4
lastName:
label: Nom
width: 1/4
email:
label: Email
width: 1/4
company:
label: Entreprise
width: 1/4
role:
label: Fonction
whitePaper:
label: Livres blancs
downloadedAt:
label: Date
sections:
export:
type: csv-export
contacts:
type: fields
fields:
firstName:
label: Prénom
type: text
contactDatabase:
label: Ont téléchargé un livre blanc
type: structure
translate: false
required: true
lastName:
label: Nom
type: text
translate: false
required: true
company:
label: Société
type: text
translate: false
role:
label: Fonction
type: text
translate: false
email:
type: email
translate: false
required: true
whitePaper:
label: Livres blancs
type: pages
translate: false
query: site.find('livres-blancs').children
downloadedAt:
type: text
translate: false
label: Date
columns:
firstName:
label: Prénom
width: 1/5
lastName:
label: Nom
width: 1/5
email:
label: Email
width: 1/5
company:
label: Entreprise
width: 1/5
role:
label: Fonction
width: 1/5
whitePaper:
label: Livres blancs
downloadedAt:
label: Date
fields:
firstName:
label: Prénom
type: text
translate: false
required: true
lastName:
label: Nom
type: text
translate: false
required: true
company:
label: Société
type: text
translate: false
role:
label: Fonction
type: text
translate: false
email:
type: email
translate: false
required: true
whitePaper:
label: Livres blancs
type: pages
translate: false
query: site.find('livres-blancs').children
downloadedAt:
type: text
translate: false
label: Date
files: tabs/files
seo: seo/page

View file

@ -0,0 +1,3 @@
.csv-export-btn {
margin-bottom: 2rem;
}

View file

@ -0,0 +1,17 @@
panel.plugin("world-game/csv-export", {
sections: {
"csv-export": {
template: `
<k-button
icon="download"
text="Exporter en CSV"
variant="filled"
theme="positive"
link="/wg-export/contacts"
target="_blank"
class="csv-export-btn"
/>
`,
},
},
});

View file

@ -0,0 +1,50 @@
<?php
Kirby::plugin('world-game/csv-export', [
'sections' => [
'csv-export' => [],
],
'routes' => [
[
'pattern' => 'wg-export/contacts',
'method' => 'GET',
'action' => function () {
if (!kirby()->user()) {
http_response_code(403);
exit;
}
$entries = page('livres-blancs')->contactDatabase()->toStructure();
header('Content-Type: text/csv; charset=UTF-8');
header('Content-Disposition: attachment; filename="' . date('ymd') . '-contacts.csv"');
header('Cache-Control: no-cache');
$out = fopen('php://output', 'w');
fputs($out, "\xEF\xBB\xBF"); // BOM pour Excel
fputcsv($out, ['Prénom', 'Nom', 'Email', 'Entreprise', 'Fonction', 'Livres blancs', 'Date'], ';');
foreach ($entries as $entry) {
$titles = [];
foreach ($entry->whitePaper()->toPages() as $wp) {
$titles[] = $wp->title()->value();
}
fputcsv($out, [
$entry->firstName()->value(),
$entry->lastName()->value(),
$entry->email()->value(),
$entry->company()->value(),
$entry->role()->value(),
implode(' | ', $titles),
$entry->downloadedAt()->value(),
], ';');
}
fclose($out);
exit;
},
],
],
]);