From 958dd5998fddef6bdbe8a879c4877bf1151d9ad0 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Thu, 5 Feb 2026 10:04:07 -0800 Subject: [PATCH 1/2] Flatten row objects and support AssignedGroups Add flattenObject helper in pdfExportButton to flatten nested row.original objects before formatting so deeply nested properties export correctly. Update exportRowsToPdf to use the flattened data and only apply getCippFormatting for keys present in the export columns. Extend getCippFormatting to handle AssignedGroups (and camelCase assignedGroups) by returning display names for text exports or a CippDataTableButton otherwise, and accept camelCase assignedUsers as well. Minor code/formatting cleanup in width calculation. --- src/components/pdfExportButton.js | 29 ++++++++++++++++++++++++----- src/utils/get-cipp-formatting.js | 16 +++++++++++++++- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/components/pdfExportButton.js b/src/components/pdfExportButton.js index 0755b6037079..f0c0ce803b08 100644 --- a/src/components/pdfExportButton.js +++ b/src/components/pdfExportButton.js @@ -5,6 +5,22 @@ import autoTable from "jspdf-autotable"; import { getCippFormatting } from "../utils/get-cipp-formatting"; import { useSettings } from "../hooks/use-settings"; +// Flatten nested objects so deeply nested properties export properly. +// This function only restructures data without formatting - formatting happens later in one pass. +const flattenObject = (obj, parentKey = "") => { + const flattened = {}; + Object.keys(obj).forEach((key) => { + const fullKey = parentKey ? `${parentKey}.${key}` : key; + if (typeof obj[key] === "object" && obj[key] !== null && !Array.isArray(obj[key])) { + Object.assign(flattened, flattenObject(obj[key], fullKey)); + } else { + // Store the raw value - formatting will happen in a single pass later + flattened[fullKey] = obj[key]; + } + }); + return flattened; +}; + // Shared helper so the toolbar buttons and bulk export path share the same PDF logic. export const exportRowsToPdf = ({ rows = [], @@ -21,7 +37,7 @@ export const exportRowsToPdf = ({ const size = "A3"; const orientation = "landscape"; const doc = new jsPDF(orientation, unit, size); - const tableData = rows.map((row) => row.original ?? row); + const tableData = rows.map((row) => flattenObject(row.original ?? row)); const exportColumns = columns .filter((c) => columnVisibility[c.id]) @@ -30,8 +46,11 @@ export const exportRowsToPdf = ({ // Use the existing formatting helper so PDF output mirrors table formatting. const formattedData = tableData.map((row) => { const formattedRow = {}; - Object.keys(row).forEach((key) => { - formattedRow[key] = getCippFormatting(row[key], key, "text", false); + exportColumns.forEach((col) => { + const key = col.dataKey; + if (key in row) { + formattedRow[key] = getCippFormatting(row[key], key, "text", false); + } }); return formattedRow; }); @@ -58,7 +77,7 @@ export const exportRowsToPdf = ({ const columnWidths = exportColumns.map((col) => { const headerLength = col.header.length; const maxContentLength = Math.max( - ...formattedData.map((row) => String(row[col.dataKey] || "").length) + ...formattedData.map((row) => String(row[col.dataKey] || "").length), ); const estimatedWidth = Math.max(headerLength, maxContentLength) * 6; return Math.min(estimatedWidth, (availableWidth / columnCount) * 1.5); @@ -66,7 +85,7 @@ export const exportRowsToPdf = ({ const totalEstimatedWidth = columnWidths.reduce((sum, width) => sum + width, 0); const normalizedWidths = columnWidths.map( - (width) => (width / totalEstimatedWidth) * availableWidth + (width) => (width / totalEstimatedWidth) * availableWidth, ); // Honor tenant branding colors when present so exports stay on-brand. diff --git a/src/utils/get-cipp-formatting.js b/src/utils/get-cipp-formatting.js index e72666e33bbd..b9a321e1cc91 100644 --- a/src/utils/get-cipp-formatting.js +++ b/src/utils/get-cipp-formatting.js @@ -636,7 +636,7 @@ export const getCippFormatting = (data, cellName, type, canReceive, flatten = tr } //handle assignedUsers - if (cellName === "AssignedUsers") { + if (cellName === "AssignedUsers" || cellName === "assignedUsers") { //show the display name in text. otherwise, just return the obj. return isText ? ( Array.isArray(data) ? ( @@ -649,6 +649,20 @@ export const getCippFormatting = (data, cellName, type, canReceive, flatten = tr ); } + // handle assignedGroups + if (cellName === "AssignedGroups" || cellName === "assignedGroups") { + //show the display name in text. otherwise, just return the obj. + return isText ? ( + Array.isArray(data) ? ( + data.map((group) => group.displayName).join(",") + ) : ( + data.displayName + ) + ) : ( + + ); + } + // Handle assigned licenses if (cellName === "assignedLicenses") { var translatedLicenses = getCippLicenseTranslation(data); From d6ea8ddc03be9e827c630ad5acc4b48438eb3392 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Thu, 5 Feb 2026 10:04:58 -0800 Subject: [PATCH 2/2] bump version to 10.0.9 --- package.json | 2 +- public/version.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index e7a888033252..231bc20bc860 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cipp", - "version": "10.0.6", + "version": "10.0.9", "author": "CIPP Contributors", "homepage": "https://cipp.app/", "bugs": { diff --git a/public/version.json b/public/version.json index 90d764a5ec57..ad15f02cceba 100644 --- a/public/version.json +++ b/public/version.json @@ -1,3 +1,3 @@ { - "version": "10.0.6" + "version": "10.0.9" } \ No newline at end of file