Skip to content

Commit

Permalink
feat: Add column filter in generated XLSX document
Browse files Browse the repository at this point in the history
This is part of story #23469: export reports with linked artifact in xlsx format

Artifact columns can now be filtered in the generated XLSX document.
The autofilter generation done by sheetjs does not work with LibreOffice
[1][2]

[1] https://bugs.documentfoundation.org/show_bug.cgi?id=118592
[2] SheetJS/sheetjs#1165

Change-Id: Iecce314804d910651df4a6d81d93068f7897a5d5
  • Loading branch information
yannis-rossetto committed Apr 19, 2022
1 parent 8484242 commit 3416842
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/**
* Copyright (c) Enalean, 2022-Present. All Rights Reserved.
*
* This file is a part of Tuleap.
*
* Tuleap is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Tuleap is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tuleap. If not, see <http://www.gnu.org/licenses/>.
*/

import { generateAutofilterRange } from "./autofilter-generator";
import type { ReportSection } from "../../Data/data-formator";
import { EmptyCell, TextCell } from "@tuleap/plugin-docgen-xlsx";

describe("autofilter-generator", () => {
it("generates the autofilter range", (): void => {
const formatted_data: ReportSection = {
headers: {
tracker_names: [],
reports_fields_labels: [
new TextCell("Field01"),
new TextCell("Field02"),
new TextCell("Field03"),
new TextCell("Field04"),
],
},
artifacts_rows: [
[
new TextCell("Value01"),
new TextCell("Value02"),
new TextCell("Value03"),
new EmptyCell(),
],
[
new TextCell("Value04"),
new TextCell("Value05"),
new EmptyCell(),
new TextCell("Value06"),
],
],
};

const autofilter_range: string = generateAutofilterRange(formatted_data);

expect(autofilter_range).toBe("A2:D4");
});
it("generates empty autofilter range if headers is missing in formatted_data", (): void => {
const formatted_data: ReportSection = {
artifacts_rows: [
[
new TextCell("Value01"),
new TextCell("Value02"),
new TextCell("Value03"),
new EmptyCell(),
],
[
new TextCell("Value04"),
new TextCell("Value05"),
new EmptyCell(),
new TextCell("Value06"),
],
],
};

const autofilter_range: string = generateAutofilterRange(formatted_data);

expect(autofilter_range).toBe("");
});
it("generates empty autofilter range if artifacts_rows is missing in formatted_data", (): void => {
const formatted_data: ReportSection = {
headers: {
tracker_names: [],
reports_fields_labels: [
new TextCell("Field01"),
new TextCell("Field02"),
new TextCell("Field03"),
new TextCell("Field04"),
],
},
};

const autofilter_range: string = generateAutofilterRange(formatted_data);

expect(autofilter_range).toBe("");
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* Copyright (c) Enalean, 2022-Present. All Rights Reserved.
*
* This file is a part of Tuleap.
*
* Tuleap is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Tuleap is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tuleap. If not, see <http://www.gnu.org/licenses/>.
*/

import type { HeadersSection, ReportSection } from "../../Data/data-formator";
import type { ReportCell } from "@tuleap/plugin-docgen-xlsx";
import { utils } from "xlsx";

const RANGE_SEPARATOR = ":";
const STARTING_COLUMN = "A";
const STARTING_ROW = 2;

export function generateAutofilterRange(formatted_data: ReportSection): string {
if (formatted_data.headers === undefined || formatted_data.artifacts_rows === undefined) {
return "";
}

const all_headers: HeadersSection = formatted_data.headers;
const all_artifacts_rows: ReadonlyArray<ReadonlyArray<ReportCell>> =
formatted_data.artifacts_rows;

return (
getAutofilterStartingRange() +
RANGE_SEPARATOR +
getAutofilterEndingRange(all_headers, all_artifacts_rows)
);
}

function getAutofilterStartingRange(): string {
return STARTING_COLUMN + STARTING_ROW.toString();
}

function getAutofilterEndingRange(
all_headers: HeadersSection,
all_artifacts_rows: ReadonlyArray<ReadonlyArray<ReportCell>>
): string {
const ending_column: string = utils.encode_col(all_headers.reports_fields_labels.length - 1);
const ending_row: number = all_artifacts_rows.length + STARTING_ROW;
return ending_column + ending_row.toString();
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
} from "@tuleap/plugin-docgen-xlsx";
import type { ExportSettings } from "../../export-document";
import { generateFilename } from "./file-name-generator";
import { generateAutofilterRange } from "./autofilter-generator";

export function downloadXLSX(export_settings: ExportSettings, formatted_data: ReportSection): void {
const book = utils.book_new();
Expand All @@ -38,6 +39,7 @@ export function downloadXLSX(export_settings: ExportSettings, formatted_data: Re
sheet["!cols"] = fitColumnWidthsToContent(cells);
sheet["!rows"] = fitRowHeightsToContent(cells);
sheet["!merges"] = createMergesForWholeRowLine(cells);
sheet["!autofilter"] = { ref: generateAutofilterRange(formatted_data) };
utils.book_append_sheet(book, sheet);
writeFile(book, generateFilename(export_settings), {
bookSST: true,
Expand Down

0 comments on commit 3416842

Please sign in to comment.