Build a slide deck sharing application with OutSystems
I only wanted to share some slides. Then I built an app with OutSystems, Adobe Acrobat Services, AWS S3 and AWS CloudFront.
Table of contents
Challenge
In November 2023, I started a webinar series on how to interact with Microsoft Graph API from OutSystems applications. To conduct these webinars, I used Microsoft Teams and uploaded the slide deck to the files section shortly before each session. During the webinars, I mentioned that participants could find the slides in the chat and the files section. Interestingly, after each webinar, I received multiple emails asking me to share the slides, and in one instance, I even received a complaint in the post-webinar survey that I hadn't shared the slide material.
I proceeded to upload the slide decks to Slideshare, aiming to provide a single link for participants to access all of my slide decks. Unfortunately, I hadn't evaluated the service thoroughly enough. For users, the slide deck previews were cluttered with advertisements, which might still be tolerable. However, users were also required to register an account to download a slide deck. This was not what I intended, so I began searching for alternatives. As I signed up for multiple slide sharing services (... and didn't like it), I wondered why I shouldn't create one myself. After all, the only features I wanted were:
The ability to upload a Microsoft PowerPoint Presentation with a title and description.
A tool that allows users to view individual slides page by page in their browser or download them as a PDF document, without needing to sign in.
Do it yourself
I quickly wrote down some notes:
User
Views all available slide decks as a gallery with a cover image, title, and publication date.
Views a single slide deck with title, description, carousel view for individual slides, and a download button for PDF download.
Me
- Upload a Microsoft PowerPoint presentation (pptx) with Title and Description
If you follow my articles or my OutSystems profile, you may know that I maintain an integration with Adobe Acrobat Services, a powerful service for document transformation.
๐ฆ Adobe Acrobat Services on OutSystems Forge
This integration, available on OutSystems Forge, helps to:
Convert a Microsoft PowerPoint Presentation to PDF
Convert individual slides to images for the carousel view
Storing documents in the OutSystems database is a no-go for me in any situation, so all documents should be stored in an Amazon Simple Storage Service (S3) bucket.
The individual, extracted slide images should be retrieved directly from the S3 bucket by the client application. However, I aim for scalability and optimal performance when loading the image files, so I added an Amazon CloudFront distribution as a CDN with the S3 bucket as the origin. A positive side effect is that I can keep my S3 bucket private and only allow the CloudFront service to retrieve files from it.
Give it a try
Before delving further into the implementation, please take a moment to visit the application at โก๏ธ https://spatium.outsystemscloud.com/Slider/
This is my personal OutSystems environment, and it contains some of my recent slide decks.
To set up your own instance, you can find the application on OutSystems Forge. Go ahead and download it to your environment.
๐ฆ Slider Demo Application on OutSystems Forge
With downloading the application you also need to download the following dependencies:
๐ฆAdobe Acrobat Services - The integration component with Adobe Acrobat Services.
๐ฆAmazon Simple Storage Service (S3) - To store and retrieve objects from Amazon S3.
๐ฆOAuth Token Exchange - Utility components for retrieving an access token from Adobe Identity Provide using a client credentials OAuth 2.0 flow.
๐ฆSlugify - Custom code extension to slugify any text.
Walkthrough
Lets start by reviewing some of the technical implementations. Lets start with the prerequisites.
Prerequisites
Adobe Acrobat Services
Read my article on Starting Out with OutSystems and Adobe Acrobat Services | by Stefan Weber | ITNEXT and register an account with Adobe Acrobat Services.
From your account note your Client Id and Client Secret and set the corresponding site properties in the Slider_BL module.
Amazon Simple Storage Service
Create a new bucket in any region with default settings. Note down the bucket name and set the AWSBucketName and AWSRegion site properties in the Slider_BL module.
Amazon Identity and Access Management
In IAM create a new Policy that grants access to the S3 bucket
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::osslides/*"
]
}
]
}
The policy above grants PutObject and GetObject permissions to all objects in the osslides bucket. For the application these are the only permissions required.
Create a new user account with this policy attached and generate access keys for this user. Set AWSAccessKey and AWSSecretAccessKey site properties in the Slider_BL module to the generated values.
Amazon CloudFront
Create a new CloudFront distribution and add the S3 bucket as the origin for the distribution. You can create the distribution using the default settings.
After clicking the create button, CloudFront will generate a bucket policy document for you. Copy the policy document and paste it into the Bucket Policy section of your newly created S3 bucket.
Note down your CloudFront distribution domain name and set the AWSCloudFrontBaseUrl site property in the Slider_BL module.
OutSystems Implementation
With all the prerequisites done you should now be able to run it in your environment.
Next let us now look at the notable implementation details.
Uploading a presentation
In the Slider_BL module open the Slider_AddPresentation server action.
This flow performs the following actions
Creates a new Presentation entity record with the Title and Description the user entered in the frontend.
Then i retrieves an access token from Adobe Identity Provider using the Client Id and Client Secret values.
It uploads the original presentation to Adobe Document Cloud.
- Last it creates a PresentationAsset entity record that stores the unique asset identifer received from Adobe Document Cloud.
Document Processing with a LightBPT process
Creating the entity record for PresentationAsset triggers a LightBPT process that performs the document processing.
In the Slider_BL module open the Automatic Activity of the ProcessDocumentUpload process.
This is a long one, but I decided to not extract the single operations into different server actions to simplify it.
In this flow
The asset key is retrieved from the PresentationAsset entity record.
Using the asset key the document is converted to a PDF document with, which generates a new asset in Adobe Document Cloud. That asset gets downloaded and is put into the S3 bucket.
From the converted PDF document the individual slides are then extracted as images. This operation generates a ZIP file in Adobe Document Cloud, which is downloaded.
From the Zip extension we use the LoadZip action to open the downloaded Zip file.
Then we iterate over the list of files that we get using the GetFiles server action.
Each Image is then stored in the S3 bucket and a Slide entity record is created for each iteration. The ordering number of the slides is extracted from the returned image file names using String_Split from the Text extension.
Last there are some cleanup actions to remove the files from Adobe Document Cloud and the PresentationAsset entity record.
Downloading a presentation
The Slider_DownloadPresentation server action retrieves the PDF document from the S3 bucket and returns it. In the frontend, the file is then downloaded.
You might wonder why we don't directly refer to the PDF file in the frontend. The reasons are cross-origin restrictions, as your CloudFront endpoint is on a different domain than your OutSystems environment.
When downloading a file directly from the browser you can use the following
<a href="https://mydomain.com/myfile.pdf" download="myfile">Download</a>
This will download the file instead of navigating to it, but only if the href is on the same origin. If it is on another origin, the browser will either block it or navigate to the file.
Retrieving a presentation
The last action we look at is the Slider_GetPresentation server action in the Slider_BL module.
This first part should be pretty self-explaining
We get the presentation details followed by
getting all associated slides ordered by the Order number
Then we iterate of the slides and construct full URL to the images.
Last we set the CoverUrl to the first slide of the slide deck.
In the Frontend module the image URLs are used as input for the carousel images.
Summary
Building this small application took me close to 2 hours. While it's not complete and there are many aspects to improve or add, the fact that it only took two hours speaks highly of OutSystems and, in particular, Forge components. The latter is the main reason why I was able to develop it so quickly.
Thank you for reading. I hope you liked it and that i have explained the important parts well. Let me know if not ๐
If you have difficulties in getting up and running, please use the OutSystems Forum to get help. Suggestions on how to improve this article are very welcome. Send me a message via my OutSystems Profile or write a comment.