Console Moodle
A terminal-based UI app to recreate a course-management system with cross-platform support with ncurses and CMake.
Published onUpdated on
2.885
Description
A terminal-based UI application as a final project for the course of
Programming Techniques to recreate Moodle, a course-management system,
utilizing cross-platform libraries like ncurses and universal build
tools like CMake.
My Role
This was partly my fault, but no one in the group was willing to learn
the ins and outs of ncurses, and wanted to rely on std::cout and
std::cin to provide a terminal-based experience, which wouldn’t be as
impressive as I wanted it to be.
My main role is to provide a Terminal UI from ncurses function calls, and use others’ implemented features (usually pure functions, data structures with no side effects).
Technical Feats
Abstraction over ncurses layer with a more centralized method to render strings on the screen better.
void draw_date_dialog(Date &date, WINDOW *window, DateTimeScreenData *data)
{
box(window, 0, 0);
renderer::draw_row(window, 2, true);
wattron(window, A_BOLD);
renderer::print_aligned(data->title).aligned(align::top | align::center).offset(1, 0).color(4).on(window).apply();
renderer::print_aligned("Day").aligned(align::top | align::left).offset(3, 1).on(window).apply();
renderer::print_aligned("Month").aligned(align::top | align::left).offset(5, 1).on(window).apply();
renderer::print_aligned("Year").aligned(align::top | align::left).offset(7, 1).on(window).apply();
renderer::print_aligned("Save").aligned(align::bottom | align::center).offset(-2, 0).on(window).apply();
renderer::print_aligned("Cancel").aligned(align::bottom | align::center).offset(-1, 0).on(window).apply();
wattroff(window, A_BOLD);
renderer::print_aligned(data->tl_day()).aligned(align::top | align::center).offset(4, 0).on(window).clear().apply();
renderer::print_aligned(data->tl_month()).aligned(align::top | align::center).offset(6, 0).on(window).clear().apply();
renderer::print_extensible(data->year).on(window).start(8, 1).end(getmaxx(window) - 2).apply();
curs_set(0);
~snip~
}
A simple abstraction of a List View that is reused across the application:
namespace graphics
{
namespace views
{
template <typename T>
struct ListViewBuilder
{
ScrollControl *controls = nullptr;
T *data;
int length;
std::function<void(WINDOW *, int)> header_painter;
std::function<void(int, int, T)> line_painter;
std::string empty_message = "There is nothing to display";
}
}
}
I wrote over 8000 lines in a 9000-LoC project. I was a machine here.
Key Features
It is better explained to view the video embedded below!
For those who are vision-impaired:
- Login Splashscreen that hides your password with
*. - Smooth UI interaction with arrow keys and Enter, just like how you expect it.
- Permission Control: Exclusive “Administrative Tools” window only if you login with the authorized account.
- Scene/Window-separation: Each window has its own handler that gets passed around the “baton” for control, such as the View (which will scroll when you use arrow keys), and you can tab to move to the Actions tab (which uses arrow keys as a way to navigate options, such as adding a new course).
- Custom floating forms: Forms that create a new item float in the middle of the screen as a separate “window context”.
- Same thing with dialogue boxes! There are two types of them: Option Choices and Info Boxes. Option Choices allow you to pick an option, such as Yes or No, and Info Boxes only have a purpose to display some information that can be closed with an Enter.
- Options are grayed out and can’t be “hovered” upon with arrow keys if they don’t have the meaningful context, or can’t be done. Such as “Delete Semester” is grayed out if “Create Semester” is available, since the semester isn’t available yet.
- Messages when the list is empty! So no List View is created.
- Scrolling options as well as instantly validating fields when inputting constrained fields such as Day, Month, Year or Gender.
- Smooth scrolling with a highlighted line to indicate current selection. The List View won’t scroll if your screen contained everything it needed to display!
- Custom-implemented radio choices with grayed out options.
- Track Student Scores via a spreadsheet, which can be imported to the system to update all related students’ final grades, midterm grades and etc.
- Cascading Deletion: Deleting a course implicitly deletes all resources that course owns (such as scores). Deleting a course also deletes it from a semester, without using any relational databases.
- Students can view their enrolled scores if the admin has added them, but not any courses they have not enrolled in. Not even view their information.