PDF export of documents

Apologies for the delay in responding. Here is the code for the action button:

// this action button uses the pdfmonkey.io API to generate pdf
// documents from fibery records/entities

// Fibery API and HTTP services
const fibery = context.getService('fibery');
const http = context.getService('http');
const utils = context.getService("utils");

// define the time zone offset (has to be hardcoded right now)
const timeOffset = {{UTC_TZ_OFFSET}};

for (const entity of args.currentEntities) {
    // get the meeting date (object with start and end)
    const meetingDateTime = entity['Date'];
    const meetingDateStart = new Date(meetingDateTime.start);
    meetingDateStart.setHours(meetingDateStart.getHours() + timeOffset);
    const meetingDateEnd = new Date(meetingDateTime.end);
    meetingDateEnd.setHours(meetingDateEnd .getHours() + timeOffset);

    // get the subject of meeting (name of entity)
    const meetingSubject = entity['Name'];

    // get the meeting notes (RTF) field
    const meetingNotes = entity['Notes'];
    const notesContent = await fibery.getDocumentContent(meetingNotes.secret, "html");

    // get collection fields query the API and provide the list of fields
    const attendeeList = await fibery.getEntityById(entity.type, entity.id, ['Attendees']);
    const nameArray = [];
    attendeeList['Attendees'].forEach(function (person) {
        nameArray.push(person.Name);
    });
    
    // call pdfmonkey.io api to generate the pdf document
    const objDocument = await http.postAsync('https://api.pdfmonkey.io/api/v1/documents', {
        body: {
            "document": {
                "document_template_id": "{{PDF_MONKEY_TEMPLATE_ID}}",
                "payload": "{ \"subject\": \"" + meetingSubject + "\", \"datestart\": \"" + meetingDateStart + "\" , \"dateend\": \"" + meetingDateEnd + "\", \"attendees\": " + JSON.stringify(nameArray) + ", \"notes\": " + JSON.stringify(notesContent) + " }",
                "status": "pending"
            }
        },
        headers: { 
            'Content-type': 'application/json', 
            'Authorization': 'Bearer {{PDF_MONKEY_API_KEY}}' }
    });

}

You will need to replace the following in the code:

  • {{UTC_TZ_OFFSET}} : replace with your timezone offset (-12 to +12)
  • {{PDF_MONKEY_TEMPLATE_ID}} : replace with your pdfmonkey.io template ID
  • {{PDF_MONKEY_API_KEY}}: replace with your pdfmonkey.io API key

I would like to add to the code to wait for the PDF to be generated and then grab the address and store it a field in the entity. I will update the codes once I’ve done that.

The template in PDF monkey can be as simple or complicated as you wish:

HTML Template

<table class="letterhead">
  <tr style="height: 40px">
    <td class="logobox" rowspan="3">LOGO</td>
    <td class="title" colspan="5">Meeting Notes</td>
  </tr>
  <tr style="height: 25px">
    <td style="width: 80px; font-weight: bold">Subject:</td>
    <td style="width: 500px; border-bottom: 1px solid #ddd;" colspan="4">{{subject}}</td>
  </tr>
  <tr style="height: 25px">
    <td style="width: 80px; font-weight: bold">Project:</td>
    <td style="width: 500px; border-bottom: 1px solid #ddd;">{{project}}</td>
    <td style="width: 5px; font-weight: bold"></td>
    <td style="width: 45px; font-weight: bold">Date:</td>
    <td style="width: 150px; border-bottom: 1px solid #ddd;">{{datestart | date: "%Y %b %-d" }}</td>
  </tr>
  <tr style="height: 25px">
    <td style="width: 120px"></td>
    <td style="width: 80px; font-weight: bold">Location:</td>
    <td style="width: 500px; border-bottom: 1px solid #ddd;">{{location}}</td>
    <td style="width: 5px; font-weight: bold"></td>
    <td style="width: 45px; font-weight: bold">Time:</td>
    <td style="width: 150px; border-bottom: 1px solid #ddd;">{{datestart | date: "%k:%M" }} - {{dateend | date: "%k:%M" }}</td>
  </tr>
</table>

<table class="letterhead">
  <tr style="height: 10px">
    <td style="width: 13px"></td>
    <td></td>
  </tr>
  <tr style="height: 2px">
    <td></td>
    <td style="border-bottom: 1px solid #000;"></td>
  </tr>
   <tr style="height: 2px">
     <td></td>
    <td style="border-bottom: 1px solid #000;"></td>
  </tr>
  <tr>
    <td></td>
    <td style="font-weight: bold">Attendees</td>
  </tr>
  <tr style="">
    <td></td>
    <td>
      <ul style="list-style-type: square">
        {% for attendee in attendees %}
          <li>{{attendee}}</li>
        {% endfor %}
      </ul>
    </td>
  </tr>
  <tr style="height: 2px">
    <td></td>
    <td style="border-bottom: 1px solid #000;"></td>
  </tr>
   <tr style="height: 2px">
     <td></td>
    <td style="border-bottom: 1px solid #000;"></td>
  </tr>
  <tr>
    <td></td>
    <td style="font-weight: bold">Notes</td>
  </tr>
  <tr>
    <td></td>
    <td class="notecontent">{{notes}}</td>
  </tr>
</table>

CSS

.letterhead {
	width: 100%;
	font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
	font-size: 11pt;
}
.title {
  font-size: 22pt;
  font-weight: bold;
}
.logobox {
  width: 120px;
}
.notecontent{
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
}

Data Structure

{
  "subject": "Test Meeting Notes",
  "project": "Testing",
  "datestart": "2021-03-05T11:00:00.000Z",
  "dateend": "2021-03-05T20:00:01.000Z",
  "location": "",
  "attendees": ["Brian Griffin", "James Woods", "Peter Griffin"],
  "notes": "This is a test"
}

Just a few caveats:

  • It seems at the moment that entity references do not resolve properly and sometimes are missing from the HTML that is returned by Fibery. The team is aware of this but I don’t know when a fix is going to be provided
  • Images in rich text area are not accessible outside of Fibery without some sort of authentication. So if you have images, those won’t should up in the generated PDF

I think it would be much better if Fibery had an internal capability to do this. I will link to this thread from the Templates thread because I think the two are related.

5 Likes