Skip to main content

Architecture Overview

Training data shares a codebase with our parent app, DB Manager. Please look there for full documentation on back-end architecture. Within this environment, Training data uses:

/src
├── controllers
├── models
├── routes
├── services
├── middleware
├── utils
├── config
├── tests
└── app.js

Backend​

Routes​

API endpoints and their associated controller methods.

// routes/userRoutes.js
const express = require("express");
const userController = require("../controllers/userController");

const router = express.Router();

router.get("/users", userController.getUser);

module.exports = router;

Services​

Complex business logic that isn’t directly tied to a specific endpoint.

// services/authService.js
const generateToken = (user) => {
// Logic to generate a JWT token
};

module.exports = {
generateToken,
};

Middleware​

Authentication, validation and error handling.

Utils​

Utility functions that can be reused across the application (p.e. formatDate).

Config​

Environment variables, database configurations…

Tests​

Unit and integration tests.

API​

API​

DescriptionEndpointMethodParamsBodyReturn
Add list of different non moodle courses/addPOST--array of course objects: [{ "id": int, "shortname": varchar, "start_date": datetime, "language": varchar, "format": varchar, "main_topic": varchar, "level": int, "edition": int, "duration": int }, ...]
GET list of all non moodle courses/getAllNMCoursesGET--array of course objects: [{ "id": int, "shortname": varchar, "start_date": datetime, "language": varchar, "format": varchar, "main_topic": varchar, "level": int, "edition": int, "duration": int }, ...]
GET column shortname from non_moodle_courses/getNMCoursesGET--array of strings: ["Course1", ...]
Add list of different non moodle enrolments/addEnrolmentPOST--array of enrolment objects: [{ "id": int, "course_shortname": varchar, "user_fullname": varchar, "email": varchar, "country": varchar, "completion_date": datetime, "progress": int, "status": int }, ...]

Frontend​

Views​

Components that hold an entire page view (containing multiple sub-components). Our only 3 views are:

├── TrainingData
├── TrainingNMCourses
├── TrainingNMEnrolments
  • TrainingData is the landing page, including 2 main buttons that will redirect to either courses or enrolments.
  • TrainingNMCourses contains a table with all actual courses, and a button that will get a form to add more non moodle courses.
  • TrainingNMEnrolments include button that will get a form to add more non moodle enrolments, and also a bulk user option were you can download an empty CSV and then upload all the enrolments.

User flow​

user flow diagram

The user:

  1. Landing on the Training Data Main Page Interface: Displays two buttons:

[Courses]

[Enrolments]

  1. Navigating to Courses Action: Clicks on the [Courses] button.

Result: Redirected to the Courses page.

  1. Adding a Non-Moodle Course Action: Clicks [Add non-Moodle course].

Form: User fills in the required course information.

Action: Submits the form.

Result: The newly added course appears in a table with other courses listed below.

  1. Returning to Main Page Action: Clicks a navigation element (e.g., Back to Training Data) to return to the main page.

  2. Navigating to Enrolments Action: Clicks on the [Enrolments] button.

Result: Redirected to the Enrolments page.

  1. Adding a Non-Moodle Enrolment Action: Clicks [Add enrolment].

Form: User fills in the enrolment information.

Action: Submits the form.

Result: Enrolment is added to the enrolment list.

  1. Bulk Upload via CSV Option: User sees a section for Bulk Upload.

Step i: Clicks [Download Empty CSV] — gets a file with required columns.

Step ii: Fills out the CSV with enrolment data.

Step iii: Clicks [Upload CSV] — submits the populated file.

Style guide​

Follow EUFMD's Engineering Guidelines. In addition to those, we do the following:

Vue API​

  • Use Vue Options API
    • There is also the new Composition API, but the original dev team was more familiar with Options format.
    • If looking up documentation, make sure the “Options” format is selected: screenshot of Vue website with Options API selected

Naming conventions​

  • custom events ($emits) in kebab-case
  • data/variable names in camelCase
  • component names should be:
    • in PascalCase
    • always multi-word: i.e.
      • ❌ Connections.vue
      • ✅ ConnectionsTable.vue
    • when components are used by only one parent: prepend with their parent name, i.e. if a Form has components Question and Answers:
      • ❌ Question.vue, Answers.vue
      • ✅ FormQuestion.vue, FormAnswers.vue
      • This ensures that related components are visually grouped together in the file structure.
    • when components are reused throughout the app: prepend with RMT. For example, if we reuse the same Button:
      • ❌ Button.vue
      • ✅ RMTButton.vue
      • This ensures that reusable components are visually grouped together in the file structure

Pinia for state management​

Read and follow tutorial here, and examples in client > src > stores.