If the COVID 19 pandemic has taught us anything, it is that virtually everything can be virtualized. Zoom lessons have become a feature of life for students. Many teachers have taken the opportunity to collect and create resources for their students through a variety of platforms. I decided to design my React Redux project to serve this demand for virtual music education resources.
This current version of my project is only “music” related in name. I hope to incorporate many features specific to music education as I continue development and roll out some live versions for friends and colleagues, but this portfolio project represents more of a vanilla LMS. Users can sign up or log in, subscribe to courses, and record their progress through the course.
The backend models for the project started simply enough with Teachers having a collection of Courses which in turn are connected to a collection of Lessons. To allow for Users to have a collection of Courses, I created a Subscription model which serves as a join table for one User and one Course. This may seem unnecessary since Users could simply have_many Courses, but I knew from the start that keeping track of a User’s progress through a course would be best stored in the actual instance of this connection.
I ended up creating a final model called LessonProgress to store this information. Every Subscription has_many LessonProgresses, and a collection of LessonProgresses is generated automatically after a Subscription is instantiated. For simplicity’s sake, a LessonProgress stores a Lesson’s Id and a “status” as a string. I chose to use a string instead of a bool to allow for future implementation of multi-state LessonProgresses, which could include “pending review”, a “failed” state of an assessment, or a status to indicate that a lesson was started but has not been completed.
The utility of an LMS depends on having a secure login for users to access their courses and progress through the content at their leisure. Therefore I turned my attention first to the task of creating a sign up and log in process. This involved a simple form component in the frontend to take the username and password for a new or returning user (To scale the project, I will likely replace this simple username structure with full name and email for communication integration and security). After validating and creating a Session, the User object is sent by the API to the frontend.
This is where I believe the Rails API will end up falling flat when I decide to take this project to development. A more robust session creation process using cookies and full scale Rails routing will likely be the first in a list of improvements to the app as I continue to scale towards production.
To keep my Redux store simple, I needed most of my data to be structured into a single user key. To accomplish this, I needed to be sure to include all of the associations within the rendered User. To do this, I created serializers for each model in my database, making sure to include the associations I needed in this file. In addition, I altered the config/initializers/active_model_serializer.rb file to read as follows:
ActiveModelSerializers.config.default_includes = ‘**’
This allows my serializers to automatically include up to two levels of associations when rendering, giving me the depth of association needed to include Users that have many Subscriptions with many LessonProgresses and one Course.
From here, I created a spiderweb of containers and components to render (depending on the user property of the store) the correct courses and lessons. Further flow control and a new set of actions allowed me to update the backend’s LessonStatus within a subscription and allow a user to progress through a course one lesson at a time.
I initially set up the app to show the courses of multiple teachers. I realized this use case was very limited for real world application, so I pivoted the application to render a single teacher’s work. I am thankful to my friend at Horn Hippie Media for allowing me to use his existing YouTube content to serve as seeds for this project, in addition to his fantastic branding!
I have to say, designing a frontend user experience has been very satisfying with React. I have learned many ins and outs of styling buttons and Router NavLinks, and I enjoyed designing a simple container style to go with the bright and bold colors from the Horn Hippie Media branding. Further improvements to the responsive styling of the navigation components will definitely come with further development, in addition to some render animations to make the user’s experience even more smooth and seamless. My goals for this project also include CReate, Update, and DElete (CRUD) for teachers, allowing production versions of the application to be “self service”. Incorporating payment and designing a paywall for the content on the app will also be essential to a production version of the app.
Overall the process of designing and building with React has been incredibly satisfying. The structure of passing properties and state between components clicks well with how I visualize the structure of the application, and creating flow controls based on the central store of information made the addition of features simple to add to the app.