Skip to content

Commit 6d2cb11

Browse files
authored
Merge pull request #150 from vincentmakes/claude/fix-compact-print-urls-CHT94
Fix print_compact flag not reaching public dataset URLs
2 parents 8d21a66 + 8df000d commit 6d2cb11

7 files changed

Lines changed: 57 additions & 10 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ All notable changes to CV Manager will be documented in this file.
44

55
Format follows [Keep a Changelog](https://keepachangelog.com/), versioning follows [Semantic Versioning](https://semver.org/).
66

7+
## [1.48.3] - 2026-04-23
8+
9+
### Fixed
10+
- **Per-section "compact print" toggle is now honored when printing from public URLs.** The Skills / Projects compact-print flag (stored in `section_visibility.print_compact`) was correctly applied on the admin page and on the public page's live-DB fallback, but any public URL that renders from a saved dataset — the default dataset served at `/`, the versioned `/v/:slug` (+ `/v/:slug/:lang`) routes, and static-site exports — ignored it, because `print_compact` (and, same shape, `print_visible`) was dropped at three points in the dataset pipeline: `gatherCvData()` in `src/server.js` didn't include the fields when building `sectionOrder` entries, and the two client-side mappers in `public-readonly/index.html` (`loadDatasetPreview` and `loadStaticData`) further stripped them while reshaping the snapshot. `renderSectionsInOrder()` reads the flag correctly — it just never saw a value, so the `.print-compact` CSS class (and its inline-text layout in `public/shared/styles.css`) was never applied and printed pages always rendered the full card grid. Added the fields to `gatherCvData()`'s snapshot and to both client mappers. While in the area, also propagated the fields through `propagateStructure()` so language-sibling datasets share the same structural choice, and preserved them on `POST /api/datasets/:id/load` and `POST /api/import` (mirroring the `section.print_compact !== undefined ? … : existing` pattern already used by `PUT /api/sections/order`) so the roundtrip stays honest. Datasets saved before this release have no flag stored and render non-compact until re-saved, which is the correct default. No schema changes, no new endpoints, no i18n strings — the CSS rules and the admin UI were already in place. Covered by a new backend test that saves a public dataset with `print_compact=true` on Skills and asserts the flag reaches `GET /api/datasets/slug/:slug` on the public port.
11+
712
## [1.48.2] - 2026-04-23
813

914
### Fixed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "cv-manager",
3-
"version": "1.48.2",
3+
"version": "1.48.3",
44
"description": "Professional CV Management System",
55
"main": "src/server.js",
66
"scripts": {

public-readonly/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ <h2 class="section-title" data-i18n="section.projects">Featured Projects</h2>
258258
}
259259
sectionOrder = data.sectionOrder.filter(s => s.visible !== false).map(s => {
260260
const fallbackName = csNameMap[s.key] || s.key;
261-
return { key: s.key, visible: s.visible, name: s.display_name || s.name || fallbackName, default_name: s.default_name || s.name || fallbackName };
261+
return { key: s.key, visible: s.visible, print_visible: s.print_visible, print_compact: s.print_compact, name: s.display_name || s.name || fallbackName, default_name: s.default_name || s.name || fallbackName };
262262
});
263263
renderSectionsInOrder();
264264
applySectionTitles(sectionOrder);
@@ -362,7 +362,7 @@ <h2 class="section-title" data-i18n="section.projects">Featured Projects</h2>
362362
}
363363
sectionOrder = datasetData.sectionOrder.filter(s => s.visible !== false).map(s => {
364364
const fallbackName = csNameMap[s.key] || s.key;
365-
return { key: s.key, visible: s.visible, name: s.display_name || s.name || fallbackName, default_name: s.default_name || s.name || fallbackName };
365+
return { key: s.key, visible: s.visible, print_visible: s.print_visible, print_compact: s.print_compact, name: s.display_name || s.name || fallbackName, default_name: s.default_name || s.name || fallbackName };
366366
});
367367
renderSectionsInOrder();
368368
applySectionTitles(sectionOrder);

src/server.js

Lines changed: 6 additions & 4 deletions
Large diffs are not rendered by default.

tests/backend.test.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,46 @@ describe('Backend API', () => {
701701
});
702702
});
703703

704+
it('saved datasets carry print_compact through to the public API', async () => {
705+
// Turn on print_compact for skills in the live DB
706+
await fetch(`${BASE_URL}/api/sections/skills/print-compact`, {
707+
method: 'PUT',
708+
headers: { 'Content-Type': 'application/json' },
709+
body: JSON.stringify({ print_compact: true }),
710+
});
711+
712+
// Create a public dataset and save the current live state into it
713+
const createRes = await fetch(`${BASE_URL}/api/datasets`, {
714+
method: 'POST',
715+
headers: { 'Content-Type': 'application/json' },
716+
body: JSON.stringify({ name: 'Compact Print Public' }),
717+
});
718+
const created = await createRes.json();
719+
await fetch(`${BASE_URL}/api/datasets/${created.id}/save`, { method: 'POST' });
720+
await fetch(`${BASE_URL}/api/datasets/${created.id}/public`, {
721+
method: 'PUT',
722+
headers: { 'Content-Type': 'application/json' },
723+
body: JSON.stringify({ is_public: true }),
724+
});
725+
726+
// Fetch the dataset via the PUBLIC server's slug endpoint —
727+
// this is what /v/:slug's client uses to render the CV
728+
const pubRes = await fetch(`${PUBLIC_URL}/api/datasets/slug/${created.slug}`);
729+
assert.strictEqual(pubRes.status, 200);
730+
const pub = await pubRes.json();
731+
const pubSkills = pub.sectionOrder.find(s => s.key === 'skills');
732+
assert.ok(pubSkills, 'skills entry present in public dataset sectionOrder');
733+
assert.strictEqual(pubSkills.print_compact, true, 'print_compact reaches the public dataset payload');
734+
735+
// Clean up — delete dataset, reset flag
736+
await fetch(`${BASE_URL}/api/datasets/${created.id}`, { method: 'DELETE' });
737+
await fetch(`${BASE_URL}/api/sections/skills/print-compact`, {
738+
method: 'PUT',
739+
headers: { 'Content-Type': 'application/json' },
740+
body: JSON.stringify({ print_compact: false }),
741+
});
742+
});
743+
704744
// --- Reorder ---
705745
it('PUT /api/reorder/:type reorders items', async () => {
706746
// Create two experiences

version.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"version": "1.48.2",
2+
"version": "1.48.3",
33
"changelog": "https://github.com/vincentmakes/cv-manager/blob/main/CHANGELOG.md"
44
}

0 commit comments

Comments
 (0)