Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/outsystems/ultimatepdf-externallogic
Port of UltimatePDF to ODC External Library
https://github.com/outsystems/ultimatepdf-externallogic
snyk-vanguard
Last synced: 5 days ago
JSON representation
Port of UltimatePDF to ODC External Library
- Host: GitHub
- URL: https://github.com/outsystems/ultimatepdf-externallogic
- Owner: OutSystems
- License: bsd-3-clause
- Created: 2023-06-30T09:55:41.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2024-12-18T15:23:40.000Z (16 days ago)
- Last Synced: 2024-12-18T16:29:00.349Z (16 days ago)
- Topics: snyk-vanguard
- Language: C#
- Size: 155 MB
- Stars: 1
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
Table of Contents
- About The Project
Getting Started
- Usage
Advance Scenarios
- Prerequisites
- Advance PDF Generation
- Screen to PDF
- External Logic call Rest API to store the PDF
- External Logic call S3 Bucket to store the PDF
- Basic page screenshot
- Add Fonts to the Report
- License
- Known Limitations
- Get in touch
- Contributing
- Testing
- Acknowledgments
## About The Project
Project that enables ODC customers to generate PDFs using modern web technologies.
This component uses the same rendering engine as Chromium (an open-source version of Google Chrome) to transform web pages into PDF documents.
This component is based on the O11 version of Ultimate PDF.
THIS CODE IS NOT SUPPORTED BY OUTSYSTEMS.
## Getting Started
This repo contains all the external code (C#) and the modules that can be used to accelerate the development of PDFs at ODC Applications.
### Prerequisites
To generate the External Logic package run
```sh
.\generate_upload_package.ps1
```### Installation
This component is published at forge. So the best way to install it on your ODC tenant is by searching for:
* UltimatePDF_ExternalLogic
* Ultimate PDF
* _(Optional)_ Template_UltimatePDF#### From the repo
The code will generate the file `UltimatePDF_ExternalLogic.zip` that can be uploaded to the ODC Portal as external logic (documentation).
Use ODC Studio to publish the modules
* Ultimate PDF.oml - Library with accelerators to use the code from the External Logic actions
* Template_UltimatePDF.oml - Application template. Use this template to create an application that is ready to use the Ultimate PDF component## Usage
The simplest way to generate a PDF is by:
1. Create an empty screen
1. Add to the screen the web block `PrintLayout` (from UltimatePDF)
1. Build the report
1. Call the server action `PrintToPDF` to generate the PDF (from UltimatePDF)## Public Elements
All the listed public elements are present in the library **Ultimate PDF**.
### Block
- **PageCount**: Displays the total number of pages. Use inside the header of footer of PrintLayout. See also: PrintLayout.
- **PageNumber**: Displays the current page number. Use inside the header of footer of PrintLayout. See also: PrintLayout.
- **PageBreak**: Force a page break.
- **SectionBreak**: Breaks a section between two PrintLayout blocks, and allows to control how pagination continues on the new section.
- **PrintLayout**: Creates a page layout, including header and footer placeholders that are repeated on every page, and a page background that can be used for watermarks and other full-bleed design elements. See also: ScreenToPDF.
- **ScreenToPDF**: Automatically converts a screen into PDF, such that any navigation to the screen automatically downloads it as a PDF.
- **HideOnPrint**: Content will not be shown on print media.
- **ShowOnPrint**: Content will only be shown on print media.### Client actions
- **OnApplicationReady_UltimatePDF**: Loads support for Ultimate PDF on reactive applications. This action must be invoked during the OnApplicationReady event. Some features of Ultimate PDF may not work otherwise.
- **ScreenToPDF_OnInitialize**: Initializes a screen that is using ScreenToPDF block. This action must be invoked during the OnInitialize event of the screen. The ScreenToPDF block will not work otherwise.
- **CurrEnvironment**: Current Environment information.
- **GetDefaultViewport**: Defines a default viewport size of 1366x768### Server actions
- **PrintToPDF**: Generates a PDF from a given URL, using the paper size and margin size from the print stylesheet.
- **PrintToPDF_Advanced**: Generates a PDF from a given URL, specifying paper size and margin size.
- **ScreenshotToPNG**: Generates a screenshot (PNG) from a given URL, using the paper size and margin size from the print stylesheet.
- **ScreenshotToPNG_Advanced**: Generates a screenshot (PNG) from a given URL, specifying paper size and margin size.
- **GetDefaultViewport**: Defines a default viewport size of 1366x768### Static Entities
- **MarginSize**: Common document margin sizes.
- **PaperSize**: Common paper sizes.## Advance Scenarios
### Prerequisites
In the instructions bellow we will assume that the application that is generating the PDFs was created based on Template_UltimatePDF. This Template creates an application that contains:
* REST API `pdf` - that implements an API to store the PDF on the application
* Entity `GeneratePDF` - contains information for the pdf and the token authentication for the the pages
* Entity `GeneratedPDF_Files` - entity where the REST API saves the PDF files
* Entity `GeneratedPDF_Logs` - entity where the REST API saves the Log files### Advance PDF Generation
1. Create a Flow named *Print*, if not present
1. Add an empty screen
1. Under the Authorization properties, select `Everyone`
1. Add an input parameter named `Token` (Data Type = Text, Is Mandatory = Yes)
1. Delete the web block `Layouts\LayoutTopMenu`
1. Fill the screen with the information to have in the PDF
1. Add `On Initialize` event, and add a call to IsPDFTokenValid with the `Token` as parameter
1. Add a if clause `IsPDFTokeValid.Valid`, and end the *False* branch with and exception `PDFTokenExpired`
1. Add `On Ready` event, and add a call to `ExpireToken` with the `Token` as parameter
1. On another screen create a button to generate the PDF
1. Call the Server Action `GeneratePDFToken`
1. Call the Server Action `PrintToPDF_Advanced`
* URL - url for the page to be generated. In this example, the screen was created at _2._
* Environment - information of the environment where the browser will be launched. Can use the output of the Client Action `CurrEnvironment`
* PaperSize - Paper size measures separated by _x_ (eg: "21.00x29.70"). Can use the Static Entity `PaperSize` from `UltimatePDF`
* MarginSize - Paper margin size separated by _x_ (eg: "2.50x3.00x2.50x3.00"). Can use the Static Entity `MarginSize` from `UltimatePDF`
* CollectLogs - If the execution of the external logic collects logs. If True, the output parameter LogsZipFile has the logs, it's empty otherwise.
* Cookies - Cookie values to be used in the browser that will be launched.
* TimeoutSeconds - Timeout in seconds the browser will wait to render and generate the PDF
* RestCaller - REST API information for the external logic to store the PDF and the LogsZipFile.
* PDF _(Output parameter)_ - The PDF file binary data. Empty if RestCaller is passed.
* LogsZipFile _(Output parameter)_ - The logs of the external logic execution. Empty if RestCaller is passed.
1. Call Download with the output parameter *PDF* of the Server Action `PrintToPDF_Advanced`### Screen to PDF
1. At the Logic table add a System Event > On Application Ready
1. Add a call to `OnApplicationReady_UltimatePDF`
1. Create a Flow named *Print*, if not present
1. Add an empty screen
1. Under the Authorization properties, select `Everyone`
1. Add an input parameter named `Token` (Data Type = Text, Is Mandatory = Yes)
1. Delete the web block `Layouts\LayoutTopMenu`
1. Add the web block `PrintLayout\ScreenToPDF`
1. Fill the screen with the information to have in the PDF
1. Add `On Initialize` event, and add a call to `IsPDFTokenValid` with the `Token` as parameter
1. Add a if clause `IsPDFTokeValid.Valid`, and end the *False* branch with and exception `PDFTokenExpired`
1. Add a call to `ScreenToPDF_OnInitialize`
1. Add `On Ready` event, and add a call to `ExpireToken` with the `Token` as parameter
1. On another screen create a link with an action on click
1. Call the Server Action `GeneratePDFToken`
1. End the flow with a destination to the screen created at 2.### External Logic call Rest API to store the PDF
The Template_UltimatePDF already creates a REST API named *pdf* with two methods *Store* and *StoreLogs*. The external logic expects the REST API to be implemented as POST methods with binary data as the body of the request. The API call uses the `Token` parameter as an authorization header.
1. Create a Flow named *Print*, if not present
1. Add an empty screen
1. Under the Authorization properties, select `Everyone`
1. Add an input parameter named `Token` (Data Type = Text, Is Mandatory = Yes)
1. Delete the web block `Layouts\LayoutTopMenu`
1. Fill the screen with the information to have in the PDF
1. Add `On Initialize` event, and add a call to IsPDFTokenValid with the `Token` as parameter
1. Add a if clause `IsPDFTokeValid.Valid`, and end the *False* branch with and exception `PDFTokenExpired`
1. On another screen create a button to generate the PDF
1. Call the Server Action `GeneratePDFToken`
1. Call the Server Action `PrintToPDF_Advanced_ToRest`, fill the RestCaller parameter
* Token - The token of the printable page, we use it for REST API authentication.
* BaseUrl - base tenant url, eg: _https://tenant.outsystems.com_
* Module - Name of the module that implements the REST API, can use `GetOwnerURLPath()`
* StorePath - Rest method URL Path to store the PDF, eg: `/rest/pdf/Store`
* LogPath - Rest method URL Path to store the logs, eg: `/rest/pdf/StoreLogs`
* The PDF will be stored at the entity `GeneratedPDF_Files`
* The Logs will be stored at the entity `GeneratedPDF_Logs`, if requested### External Logic call S3 Bucket to store the PDF
More information on S3 buckets and presigned urls can be found in official AWS documentation.
1. Create a Flow named *Print*, if not present
1. Add an empty screen
1. Under the Authorization properties, select `Everyone`
1. Add an input parameter named `Token` (Data Type = Text, Is Mandatory = Yes)
1. Delete the web block `Layouts\LayoutTopMenu`
1. Fill the screen with the information to have in the PDF
1. Add `On Initialize` event, and add a call to IsPDFTokenValid with the `Token` as parameter
1. Add a if clause `IsPDFTokeValid.Valid`, and end the *False* branch with and exception `PDFTokenExpired`
1. On another screen create a button to generate the PDF
1. Call the Server Action `GeneratePDFToken`
1. Call the Server Action `PrintToPDF_Advanced_ToS3`, fill the S3Endpoints parameter
* PdfPreSignedUrl - Presigned url to a S3 Bucket to store the resulting PDF
* LogsPreSignedUrl - Presigned url to a S3 Bucket to store the resulting logs### Basic page screenshot
1. Create an empty screen
1. Add to the screen the web block `PrintLayout` (from UltimatePDF)
1. Build the report
1. Call the server action `ScreenshotToPNG` to generate the image (from UltimatePDF)### Add Fonts to the Report
The library uses Google Fonts to download the fonts for the PDF generation. Fonts added using these methods need to be available in the Google Fonts.
1. At the report page on the OnInitialize action add `SetDocumentFont`
1. If the font you need is not present on the static entity `Fonts`, call the `AddFontFamilyToDocument` to the add the custom font.## License
BSD-3 license. See LICENSE for more information.
## Known Limitations
* Ultimate PDF doesn’t support the IP Filtering feature. Enabling this feature in a stage will result in the reports returning a 403 error page. According to OutSystems documentation, the external libraries run on “an external service” outside the realm of the tenant applications. Because of this, Ultimate PDF fails to call the report page to render the PDF.
* The screens to print cannot be protected by authentication. We recommend the screens to be protected by tokens. See the usage of `GeneratePDFToken` on this documentation for examples.
* The input and output payload of the external logic cannot be greater than 5.5MB. Workaround use the REST API Store functionality.
* The version of chromium bundle with the forge component only has Open Sans font installed meaning it only supports a subset of languages. As a workaround the customer can add the needed fonts as css (https://developers.google.com/fonts/docs/getting_started).
* ODC has a time limit for running external logic (custom code). The current configuration is 95 seconds (documentation). Any call to this library that takes more than 95 seconds will fail with a timeout. If you are getting a 95 seconds timeout please consider: 1) Reviewing the report (screen) logic to try and improve its performance; 2) using a different library that does not rely on rendering the page on demand to generate the PDF.
* To check if you are affected by this check the Traces to see if you have a message like "OS-BERT-ELR-61302 - Running this action's custom code has exceeded the timeout limit of 95 seconds.".
* The first execution of the UltimatePDF external logic normally is slower than 10 seconds. This results in the request timing out. The main reason for this slowness is the fact that we need to prepare a chromium browser to run the requests, and then the render of the page. In an interval of 10 to 15 minutes this penalty is reduced since the external logic infrastructure is reused. The best workaround for this limitation is to set a Server Request Timeout greater than 10 seconds.
* To check if you are affected by this check the Traces to see if you have a timeout.## Get in touch
Help us improve `UltimatePDF-ExternalLogic` by either:
* Submitting an issue with detailed information about the problem you're having
* Sending us an email with any feedback or questions that you may have## Contributing
1. Do a repository Fork;
1. Create a branch based in the branch master (latest & greatest release);
1. Open the branch with you favorite C# code editor;
1. Make your code change;
1. Document your code;
1. Install the external logic in your tenant and test;
1. Kept the branch updated with the master branch and also synchronized with the upstream master;
1. Create a PR, describing what was the (mis)behavior, what you changed and please provide a sample;
1. Address any feedback in code review.## Testing
At the oml folder, there is an application named Ultimate PDF Tests that contains multiple examples and tests of the component. All the pull requests will be tested against the test application scenarios. Use this application to test your changes before sending the PR.
## Acknowledgments
Project base on OutSystems Forge component Ultimate PDF.