Build a slide deck sharing application with OutSystems

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.

ยท

8 min read

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:

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.

๐Ÿ’ก
The article contains outdated information. It states that the trial ends after 6 months. However, Adobe Acrobat Services now offers a free usage tier that limits the number of free operations per month, and this free tier does not expire after 6 months.

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.

๐Ÿ’ก
Please note that you have to set AWSRegion to the region short name (e.g. EUCentral1) and not the system name (e.g. eu-central-1). A complete list of Region endpoints can be found here AWS SDK for .NET V3 API Documentation (amazon.com)

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.

๐Ÿ’ก
You should try out if objects you put in your S3 bucket are now publicly available via CloudFront. Put an image to your S3 bucket and try to view it in your browser via the CloudFront endpoint URL + filename.

Note down your CloudFront distribution domain name and set the AWSCloudFrontBaseUrl site property in the Slider_BL module.

๐Ÿ’ก
Only put the domain name

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.

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.

๐Ÿ’ก
To perform actions on a document uploading it to Adobe Document Cloud is mandatory. All following actions like converting the document to PDF can only be performed with already uploaded documents.
  • 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.

๐Ÿ’ก
Check the configuration in the Slider_BL module under Operation that Light-BPT processing is enabled.

In the Slider_BL module open the Automatic Activity of the ProcessDocumentUpload process.

Process Document Upload

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.

Silder_GetPresentation server action

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.

ย