diff --git a/src/report/common.js b/src/report/common.js index 74730a1..e0098ce 100644 --- a/src/report/common.js +++ b/src/report/common.js @@ -1,11 +1,19 @@ +/** + * A set of common utilities for creating HTML and DOCX reports for mediumroast.io objects + * @author Michael Hay + * @file common.js + * @copyright 2022 Mediumroast, Inc. All rights reserved. + * @license Apache-2.0 + */ + // Import modules import docx from 'docx' import * as fs from 'fs' import boxPlot from 'box-plot' -// TODO Change class names to: GenericHelpers, DOCXHelpers and HTMLHelpers -// rankTags belongs to GenericHelpers +// TODO Change class names to: GenericUtilities, DOCXUtilities and HTMLUtilities +// TODO rankTags belongs to GenericUtilities class Utilities { constructor (font, fontSize, textFontSize, textFontColor) { @@ -22,7 +30,7 @@ class Utilities { } } - // Initialize the common styles for the doc + // Initialize the common styles for the docx initStyles () { const hangingSpace = 0.18 return { @@ -251,14 +259,23 @@ class Utilities { }) } - // Create a text run - makeTextrun(text, spaceAfter) { - return new docx.TextRun({ - text: text, - font: this.font, - size: 16, - // break: spaceAfter ? spaceAfter : 1 - }) + // Create a text run with or without space after + makeTextrun(text, spaceAfter=false) { + const myFontSize = 16 + if (spaceAfter) { + return new docx.TextRun({ + text: text, + font: this.font, + size: myFontSize, + break: 1 + }) + } else { + return new docx.TextRun({ + text: text, + font: this.font, + size: myFontSize + }) + } } // Create a page break @@ -294,6 +311,21 @@ class Utilities { }) } + // Create an external hyperlink + makeExternalHyperLink(text, link) { + return new docx.ExternalHyperlink({ + children: [ + new docx.TextRun({ + text: text, + style: 'Hyperlink', + font: this.font, + size: 16 + }) + ], + link: link + }) + } + // Create an internal hyperlink makeInternalHyperLink(text, link) { return new docx.InternalHyperlink({ @@ -302,7 +334,7 @@ class Utilities { text: text, style: 'Hyperlink', font: this.font, - size: 1.5 * this.size, + size: 16, }), ], anchor: link, @@ -310,9 +342,9 @@ class Utilities { } // Create a bookmark needed to create an internal hyperlink + // TODO at some point test this makeBookmark(text, ident) { return new docx.Paragraph({ - heading: docx.HeadingLevel.HEADING_2, children: [ new docx.Bookmark({ id: String(ident), @@ -324,21 +356,38 @@ class Utilities { }) } - // Create an external hyperlink - makeExternalHyperLink(text, link) { - return new docx.ExternalHyperlink({ + // Create a bookmark needed to create an internal hyperlink + makeHeadingBookmark1(text, ident) { + return new docx.Paragraph({ + heading: docx.HeadingLevel.HEADING_1, children: [ - new docx.TextRun({ - text: text, - style: 'Hyperlink', - font: this.font, - size: 1.5 * this.fontSize + new docx.Bookmark({ + id: String(ident), + children: [ + new docx.TextRun({text: text}) + ] }) - ], - link: link + ] }) } + // Create a bookmark needed to create an internal hyperlink + makeHeadingBookmark2(text, ident) { + return new docx.Paragraph({ + heading: docx.HeadingLevel.HEADING_2, + children: [ + new docx.Bookmark({ + id: String(ident), + children: [ + new docx.TextRun({text: text}) + ] + }) + ] + }) + } + + + // Basic table row to produce a name/value pair basicRow (name, data) { // return the row diff --git a/src/report/companies.js b/src/report/companies.js index c034476..f1099d1 100644 --- a/src/report/companies.js +++ b/src/report/companies.js @@ -220,9 +220,11 @@ class CompanyStandalone { ' package is opened.' this.util = new Utilities() this.topics = this.util.rankTags(this.company.topics) - this.comparison = company.comparison + this.comparison = company.comparison, + this.noInteractions = String(Object.keys(this.company.linked_interactions).length) } + // TODO Move to common.js makeIntro () { const myIntro = [ this.util.makeHeading1('Introduction'), @@ -257,8 +259,13 @@ class CompanyStandalone { ], companySection.makeComparison(this.comparison), [ this.util.makeHeading1('Topics'), + this.util.makeParagraph( + 'The following topics were automatically generated from all ' + + this.noInteractions + ' interactions associated to this company.' + ), + this.util.makeHeading2('Topics Table'), this.util.topicTable(this.topics), - this.util.makeHeading1('Interaction Summaries') + this.util.makeHeadingBookmark1('Interaction Summaries', 'interaction_summaries') ], ...interactionSection.makeDescriptions(), [ this.util.pageBreak(), diff --git a/src/report/interactions.js b/src/report/interactions.js index f62df6a..cbd6036 100644 --- a/src/report/interactions.js +++ b/src/report/interactions.js @@ -159,12 +159,17 @@ class InteractionSection { // Generate the descriptions for interactions makeDescriptions () { + // TODO create bookmark with the right kind of heading const noInteractions = this.interactions.length let myRows = [this.util.descriptionRow('Id', 'Description', true)] + // TODO ids should be hyperlinks to the actual interaction which is interaction_ for (const interaction in this.interactions) { myRows.push(this.util.descriptionRow( - this.interactions[interaction].id, this.interactions[interaction].description + this.util.makeInternalHyperLink( + this.interactions[interaction].id, 'interaction_' + String(this.interactions[interaction].id) + ), + this.interactions[interaction].description ) ) } @@ -183,7 +188,7 @@ class InteractionSection { this.util.makeParagraph( 'This section contains descriptions for the ' + noInteractions + ' interactions associated to the ' + this.objectName + ' ' + this.objectType + ' object. Additional detail is in ' + - 'the Interactions Summary section of this document.' + 'the References section of this document.' ), myTable ] @@ -193,8 +198,8 @@ class InteractionSection { makeReferences(isPackage, independent=false) { // Link this back to the descriptions section const descriptionsLink = this.util.makeInternalHyperLink( - 'Interaction Descriptions', - 'interaction_descriptions' + 'Back to Interaction Summaries', + 'interaction_summaries' ) // Create the array for the references with the introduction @@ -212,9 +217,9 @@ class InteractionSection { // Create the link to the underlying interaction document const objWithPath = this.interactions[interaction].url.split('://').pop() const myObj = objWithPath.split('/').pop() - let interactionLink = this.util.urlRow( - 'Interaction Name', - this.interactions[interaction].name, './interactions/' + myObj + let interactionLink = this.util.makeExternalHyperLink( + 'Interaction Document', + './interactions/' + myObj ) // Depending upon if this is a package or not create the metadata strip with/without document link @@ -222,16 +227,19 @@ class InteractionSection { if(isPackage) { // Package version of the strip metadataStrip = new docx.Paragraph({ + spacing: { + before: 100, + }, children: [ - this.util.makeTextrun('[ ', 0), + this.util.makeTextrun('[ '), interactionLink, this.util.makeTextrun( ' | Creation Date: ' + this.interactions[interaction].creation_date + - ' | ', 0 + ' | ' ), descriptionsLink, - this.util.makeTextrun(' ]', 0), + this.util.makeTextrun(' ]'), ] }) } else { @@ -260,7 +268,7 @@ class InteractionSection { // Push all of the content into the references array references.push( // Create the bookmark for the interaction - this.util.makeBookmark( + this.util.makeHeadingBookmark2( this.interactions[interaction].name, String( 'interaction_' +