fix(pdf): fix missing logos and product images in datasheets, update pipeline
Build & Deploy / 🔍 Prepare (push) Successful in 10s
Build & Deploy / 🧪 QA (push) Successful in 2m20s
Build & Deploy / 🏗️ Build (push) Successful in 3m56s
Build & Deploy / 🚀 Deploy (push) Successful in 22s
Build & Deploy / 🧪 Post-Deploy Verification (push) Failing after 4m30s
Build & Deploy / 🔔 Notify (push) Successful in 2s

This commit is contained in:
2026-03-08 01:55:52 +01:00
parent 7583540de2
commit d575e5924a
58 changed files with 67 additions and 25 deletions
+21 -4
View File
@@ -197,6 +197,7 @@ interface ProductData {
applicationHtml?: string;
images?: string[];
featuredImage?: string | null;
logoDataUrl?: string | null;
categories?: Array<{ name: string }>;
attributes?: Array<{ name: string; options: string[] }>;
}
@@ -204,7 +205,7 @@ interface ProductData {
export interface PDFDatasheetProps {
product: ProductData;
locale: 'en' | 'de';
logoUrl?: string;
logoDataUrl?: string | null;
technicalItems?: KeyValueItem[];
voltageTables?: DatasheetVoltageTable[];
legendItems?: KeyValueItem[];
@@ -485,8 +486,15 @@ export const PDFDatasheet: React.FC<PDFDatasheetProps> = ({
<Page size="A4" style={styles.page}>
<View style={styles.hero}>
<View style={styles.header}>
<View>
<Text style={styles.logoText}>KLZ</Text>
<View style={{ width: 80 }}>
{product.logoDataUrl || (product as any).logoDataUrl ? (
<Image
src={product.logoDataUrl || (product as any).logoDataUrl}
style={{ width: '100%', objectFit: 'contain' }}
/>
) : (
<Text style={styles.logoText}>KLZ</Text>
)}
</View>
<Text style={styles.docTitle}>{labels.productDatasheet}</Text>
</View>
@@ -586,7 +594,16 @@ export const PDFDatasheet: React.FC<PDFDatasheetProps> = ({
</View>
<View style={styles.footer} fixed>
<Text style={styles.footerBrand}>KLZ CABLES</Text>
<View style={{ width: 60 }}>
{product.logoDataUrl || (product as any).logoDataUrl ? (
<Image
src={product.logoDataUrl || (product as any).logoDataUrl}
style={{ width: '100%', objectFit: 'contain' }}
/>
) : (
<Text style={styles.footerBrand}>KLZ CABLES</Text>
)}
</View>
<Text style={styles.footerText}>
{new Date().toLocaleDateString(locale === 'en' ? 'en-US' : 'de-DE', {
year: 'numeric',
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+30 -15
View File
@@ -15,6 +15,7 @@ SOURCE_ENV="${1:-}" # local | testing | staging | prod
TARGET_ENV="${2:-}" # testing | staging | prod
SSH_HOST="root@alpha.mintel.me"
LOCAL_MEDIA_DIR="./public/media"
LOCAL_DATASHEETS_DIR="./public/datasheets"
DRY_RUN=""
CHECKSUM=""
@@ -38,6 +39,16 @@ get_media_path() {
esac
}
get_datasheets_path() {
case "$1" in
local) echo "$LOCAL_DATASHEETS_DIR" ;;
testing) echo "/home/deploy/sites/testing.klz-cables.com/public/datasheets" ;;
staging) echo "/home/deploy/sites/staging.klz-cables.com/public/datasheets" ;;
prod|production) echo "/home/deploy/sites/klz-cables.com/public/datasheets" ;;
*) echo "❌ Unknown environment: $1"; exit 1 ;;
esac
}
get_app_container() {
case "$1" in
testing) echo "klz-testing-klz-app-1" ;;
@@ -52,35 +63,39 @@ TGT_PATH=$(get_media_path "$TARGET_ENV")
TGT_CONTAINER=$(get_app_container "$TARGET_ENV")
echo "🚀 Syncing assets: $SOURCE_ENV → $TARGET_ENV"
echo "📂 Source: $SRC_PATH"
echo "📂 Target: $TGT_PATH"
# ── Execution ──────────────────────────────────────────────────────────────
if [[ ! -d "$SRC_PATH" ]] && [[ "$SOURCE_ENV" == "local" ]]; then
echo "❌ Source directory does not exist: $SRC_PATH"
exit 1
fi
# ── Media Sync ─────────────────────────────────────────────────────────────
echo "🖼️ Syncing Media..."
if [[ "$SOURCE_ENV" == "local" ]]; then
# Local → Remote
echo "📡 Running rsync..."
rsync -avzi $CHECKSUM --delete --progress $DRY_RUN "$SRC_PATH/" "$SSH_HOST:$TGT_PATH/"
elif [[ "$TARGET_ENV" == "local" ]]; then
# Remote → Local
mkdir -p "$LOCAL_MEDIA_DIR"
echo "📡 Running rsync..."
rsync -avzi $CHECKSUM --delete --progress $DRY_RUN "$SSH_HOST:$SRC_PATH/" "$TGT_PATH/"
else
# Remote → Remote (e.g., testing → staging)
echo "📡 Running remote rsync..."
ssh "$SSH_HOST" "rsync -avzi $CHECKSUM --delete --progress $DRY_RUN $SRC_PATH/ $TGT_PATH/"
fi
# ── Datasheets Sync ────────────────────────────────────────────────────────
echo "📄 Syncing Datasheets..."
SRC_DS_PATH=$(get_datasheets_path "$SOURCE_ENV")
TGT_DS_PATH=$(get_datasheets_path "$TARGET_ENV")
if [[ "$SOURCE_ENV" == "local" ]]; then
ssh "$SSH_HOST" "mkdir -p $TGT_DS_PATH"
rsync -avzi $CHECKSUM --delete --progress $DRY_RUN "$SRC_DS_PATH/" "$SSH_HOST:$TGT_DS_PATH/"
elif [[ "$TARGET_ENV" == "local" ]]; then
mkdir -p "$LOCAL_DATASHEETS_DIR"
rsync -avzi $CHECKSUM --delete --progress $DRY_RUN "$SSH_HOST:$SRC_DS_PATH/" "$TGT_DS_PATH/"
else
ssh "$SSH_HOST" "mkdir -p $TGT_DS_PATH && rsync -avzi $CHECKSUM --delete --progress $DRY_RUN $SRC_DS_PATH/ $TGT_DS_PATH/"
fi
# Fix ownership on remote target if it's not local
if [[ "$TARGET_ENV" != "local" && -z "$DRY_RUN" ]]; then
echo "🔑 Fixing media file permissions on $TARGET_ENV..."
ssh "$SSH_HOST" "docker exec -u 0 $TGT_CONTAINER chown -R 1001:65533 /app/public/media/ 2>/dev/null || true"
echo "🔑 Fixing datasheet permissions..."
ssh "$SSH_HOST" "chown -R 1001:1001 $TGT_DS_PATH 2>/dev/null || true"
fi
echo "✅ Asset sync complete!"
+12 -5
View File
@@ -268,7 +268,10 @@ async function processChunk(
}
// Load assets as Data URLs for React-PDF
const heroDataUrl = await loadImageAsPngDataUrl(model.product.heroSrc);
const [heroDataUrl, logoDataUrl] = await Promise.all([
loadImageAsPngDataUrl(model.product.heroSrc),
loadImageAsPngDataUrl('/logo-black.svg'),
]);
const fileName = generateFileName(product, locale);
const voltageType = (product as any).voltageType || 'other';
@@ -281,14 +284,18 @@ async function processChunk(
// Render using the unified component
const element = (
<PDFDatasheet
product={{
...model.product,
featuredImage: heroDataUrl,
}}
product={
{
...model.product,
featuredImage: heroDataUrl,
logoDataUrl,
} as any
}
locale={locale}
technicalItems={model.technicalItems}
voltageTables={model.voltageTables}
legendItems={model.legendItems}
logoDataUrl={logoDataUrl}
/>
);
+4 -1
View File
@@ -147,7 +147,10 @@ function compactCellForDenseTable(
function resolveMediaToLocalPath(urlOrPath: string | null | undefined): string | null {
if (!urlOrPath) return null;
if (urlOrPath.startsWith('/')) return urlOrPath;
if (urlOrPath.startsWith('/')) {
// Handle Payload API URL prefix: /api/media/file/filename.ext -> /media/filename.ext
return urlOrPath.replace(/^\/api\/media\/file\//, '/media/');
}
if (/^media\//i.test(urlOrPath)) return `/${urlOrPath}`;
const mapped = ASSET_MAP[urlOrPath];
if (mapped) {