When I was an Elementary School English teacher in Korea, I often had to make PowerPoint presentations to introduce new vocabulary. Many of these presentations followed the same format. They contained images, the new vocabulary word and a translation. They were tedious to make and edit. I wanted to automate the process. I learned how to use PowerPoint Macros to automate positioning images. This was a slight improvement. I then made an image and translation downloader app to automate the task further. In this app, a list of vocabulary words is added to a form and submitted to a back end. An automated browser is then run using Selenium. It was used to obtain Korean translations for the words from Papago (a translation website) and images from Bing. I am no longer an English teacher, but I thought it would be a cool project to improve the app even further. I wanted to make a version that was more user friendly. The purpose of the app is to speed up the process of creating PowerPoint presentations that introduce new vocabulary.
A user logs in using their email or Google authentication. They then use a word list to create a PowerPoint presentation. A user can select word lists from Korean Elementary School textbook lessons or some commonly used vocabulary word lists such as verbs or animals. They can also create and save their own word lists. Once a user has selected or created a word list, they can create a PowerPoint presentation. For each word in the word list, the user selects an image or uploads an image from their pc. The user is then shown a form where they can select options for the PowerPoint presentation such as the font type, background colour, translation language and layout types. The created PowerPoint presentation is downloaded to the user's Downloads folder.
Material UI (MUI) was chosen as a component library to make use of the well-tested components that I knew I would need instead of making them from scratch. I also like the base styling, which I further modified.
Redis, along with node-rate-limiter-flexible, was used for rate limiting certain routes. This was done to protect from brute force attacks and for rate-limiting the APIs for each user. Cloudinary was used to store textbook cover images.
Selecting images for each word
For each word in the word list used to create a PowerPoint presentation, the user selects an image from Unsplash or an image from their pc. The MUI Dialog component was very useful to create a sequence of dialogs for each word. The user selects an image in each dialog. After selecting the images, another dialog gives the user a form with options for the PowerPoint presentation layout.
Storing word lists
The user's word lists are saved in MongoDB. The user can edit, combine, delete or re-order the word lists. React Query was used to make fetching, synchronizing and updating word lists efficient. It lead to a better user experience because data is not fetched unnecessarily, there were fewer loading spinners after adding it.
Word lists for Korean Elementary School curriculum books and word lists for some common topics were added to the lists page. The word lists are fetched using React Query. The user can select up to 3 lists that can then be used to create a PowerPoint presentation. The user is re-directed to the create page and the word list form is auto-populated with their selected word lists. The word lists state is global, it makes use of the React Context API. This allows easy sharing of the state between pages.
An admin page was created to make adding textbook information and word lists easy. The book images are uploaded to Cloudinary. There is also a page where the admin can view signed up users (username and authentication type) and delete them if needed. The user list is paginated and React Query is used to fetch each page and cache previously viewed pages.
Difficult problems faced
Fitting different length text into a PowerPoint slide
A function was used to find the largest font size, in pixels, that allows a vocabulary word to fit in the width of the PowerPoint slide. For each vocabulary word added to a slide, its width depends on the word length, font family and whether the text is bold or italicized. The function makes use of the canvas element to calculate the width of a given word, in pixels. It also uses a binary search to find the best font size for a given word that will allow it to fit in the PowerPoint slide. The function works ok, but the fit could be better. I plan to improve it in the future.
Unsplash API restarted each time that a dialog was displayed
I had an issue when navigating the sequence of dialogs for each word. The Unsplash API calls for the images were called each time the dialog was navigated to. The problem was that each dialog was mounting and unmounting. The solution was surprisingly simple: add the
keepMounted property to the MUI
Dialog component. This kept all the dialogs in the DOM, so they kept their state. This is useful because a user can go back and choose a different image if needed.
I plan to add more templates, nicely designed ones that can be widely used. The current templates are very basic. I also plan to add other image sources such as Google or Bing and GIFs from GIPHY.