Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cipp",
"version": "10.0.6",
"version": "10.0.9",
"author": "CIPP Contributors",
"homepage": "https://cipp.app/",
"bugs": {
Expand Down
2 changes: 1 addition & 1 deletion public/version.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"version": "10.0.6"
"version": "10.0.9"
}
29 changes: 24 additions & 5 deletions src/components/pdfExportButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [],
Expand All @@ -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])
Expand All @@ -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;
});
Expand All @@ -58,15 +77,15 @@ 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);
});

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.
Expand Down
16 changes: 15 additions & 1 deletion src/utils/get-cipp-formatting.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) ? (
Expand All @@ -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
)
) : (
<CippDataTableButton data={data} tableTitle="Assigned Groups" />
);
}

// Handle assigned licenses
if (cellName === "assignedLicenses") {
var translatedLicenses = getCippLicenseTranslation(data);
Expand Down