PBL3 Documentation Help

System Design Diagrams

Application Design

Languages

  • C#

  • XAML

Frameworks / Libraries

  • Avalonia - Develop Desktop, Embedded, Mobile and WebAssembly apps with C# and XAML

  • FluentAvalonia - Control library focused on fluent design and bringing more WinUI controls into Avalonia

  • MessageBox.Avalonia - MessageBox for AvaloniaUI

  • Autofac - .NET IoC container

  • OpenAI Dotnet - Official .NET library for the OpenAI API

  • CommunityToolkit.Mvvm - .NET MVVM library with helpers

  • HotAvalonia - .NET library crafted to seamlessly integrate hot reload functionality into Avalonia applications

  • Serilog - Simple .NET logging with fully-structured events

  • NRedisStack - Redis Stack .Net client

Build System

  • MSBuild - Build platform for .NET and Visual Studio

Testing

  • Xunit - Free, open source, community-focused unit testing tool for .NET

  • Moq - Mocking framework for .NET

Development Tools

Context Diagram

ContextDiagram

Component

Description

Course Recommendation System

Central system that processes user queries, generates course recommendations, and manages user and course data.

Student

Users of the system who seek recommendations for courses and manage their course selections.

Admin

Administrators who use the system to access aggregated data on user interactions and course selections for analysis and decision-making.

System Database

The storage system for user data, thread data, course information, and other related data required by the course recommendation system.

OpenAI API

External API used to process user queries and generate course recommendations using natural language processing and machine learning.

Component Diagram

ComponentDiagram.png

Component

Description

User Interface

Provides a user-friendly interface for students to interact with the course recommendation system.

Academic Calendar

Provides the User Interface component access to the academic calendar.

Feedback System

Allows students to post threads and view other users' threads.

OpenAI API

Analyzes user queries, extracts relevant information, and processes course descriptions to provide course recommendations.

User Database

Stores and manages user account information, including login credentials and profile information.

Course Database

Stores and manages the university's course catalog data, including course descriptions, credits, prerequisites, instructor information, and schedules.

Forum Database

Stores and manages the threads and posts of the community forums.

Use cases

UseCaseDiagram

Number

Name

Description

U1

Register Account

Register an account on the system.

U2

Log In

Log into the system.

U3

View and Edit Account Information

View and edit account information.

U4

Reset Account Password

Reset and recover account password.

U5

Delete Account

Delete account from the system.

U6

View Academic Calendar

View school's academic calendar.

U7

View and Bookmark Course Pathways

View and bookmark wanted course.

U8

Filter Courses

Filter course based on chosen property.

U9

Obtain Course Recommendation from Query

Gain course recommendations from query.

U10

Submit Course Feedback

Submit course feedback in the system.

U11

Access and Analyze User Data

University officials can access and analyze user data.

U12

Create and Delete Thread

Users can create and delete threads.

U13

Create, Edit, Reply, and Delete Post

Users can create, edit, reply and delete posts.

Use Case "Register Account" (U1)

(U1) Class Diagram

ClassDiagramU1_1.png

Class

Attributes

Methods

Associations

User

UserName: String


Password: String


Email: String


IsAdmin: Boolean

None

- 1 to * with Admin


- 1 to * with Student


- 1 to 1 with UserService

Student

StudentId: int

None

- 1 to 1 with User

Admin

None

None

- 1 to 1 with User

RegisterWindowViewModel

Email: String


Password: String


Username: String


UserService: IUserService

RegisterCommand(): void

- 1 to 1 with IUserService

IRegisterWindowViewModel

None

None

- 1 to 1 with RegisterWindowViewModel

RegisterWindow

None

RegisterWindow(): void


InitializeComponents(): void

- 1 to 1 with Window

Window

None

None

- 1 to 1 with RegisterWindow

IUserService

None

Login(key: String, password: String): Boolean


Register(user: User): Boolean


Delete(): Boolean


ResetPassword(): Boolean

- 1 to 1 with UserService

UserService

Logger: ILogger


MessageBoxService: IMessageBoxService


DatabaseService: IDatabaseService


User: User

Login(key: String, password: String): Boolean


Register(user: User): Boolean


Delete(): Boolean


ResetPassword(): Boolean

- 1 to 1 with IUserService


- 1 to 1 with ILogger


- 1 to 1 with MessageBoxService


- 1 to 1 with IDatabaseService


- 1 to 1 with User

IMessageBoxService

None

MessageBox(title: String, content: String, icon: Icon): void


ErrorMessageBox(title: String, exception: Exception, icon: Icon): void

- 1 to 1 with MessageBoxService

MessageBoxService

MessageBoxTitle: String


Message: String


Exception: Exception


Icon: Icon

MessageBox(title: String, content: String, icon: Icon): void


ErrorMessageBox(title: String, exception: Exception, icon: Icon): void

- 1 to 1 with IMessageBoxService

IDatabaseService

None

SaveUser(user: User): Boolean


GetAllThreadsFromDatabase(): Thread[]


DeleteThread(thread: Thread): Boolean


GetAggregatedDataAsync(): void


GetUsersFromDatabase(): User[]


GetThreadFromId(threadId: int): Thread


SaveCourseInformation(course: CourseInformation): Boolean


GetCourseInformationFromName(courseName: String): CourseInformation


GetDataForAnalysisAsync(): void


GetUserFromKey(key: String): User


SaveThread(thread: Thread): Boolean

- 1 to 1 with UserService


- 1 to 1 with DatabaseService

DatabaseService

Logger: ILogger

SaveUser(user: User): Boolean


GetAllThreadsFromDatabase(): Thread[]


DeleteThread(thread: Thread): Boolean


GetAggregatedDataAsync(): void


GetUsersFromDatabase(): User[]


GetThreadFromId(threadId: int): Thread


SaveCourseInformation(course: CourseInformation): Boolean


GetCourseInformationFromName(courseName: String): CourseInformation


GetDataForAnalysisAsync(): void


GetUserFromKey(key: String): User


SaveThread(thread: Thread): Boolean

- 1 to 1 with IDatabaseService


- 1 to 1 with ILogger

ILogger

None

None

- 1 to 1 with UserService


- 1 to 1 with DatabaseService

ObservableValidator

None

None

- 1 to 1 with RegisterWindowViewModel

ViewModelBase

None

None

- 1 to 1 with RegisterWindowViewModel

(U1) Sequence Diagram

SequenceDiagramU1.png

Actor: User

System Components: User Interface, AuthenticationService, Database

Step

Description

1

User initiates the registration process by accessing the registration form on the User Interface.

2

User fills out the registration form with necessary details (username, password, email, etc.).

3

User Interface sends the filled-out registration form data to the AuthenticationService.

4

AuthenticationService receives the registration data and performs initial validations:

- Validates the format of the email.

- Checks if the password meets the security criteria.

- Ensures the username is not already taken (involves a quick check with the Database).

5

If any validation fails, AuthenticationService sends an error message back to the User Interface, which then displays it to the User.

6

If all validations pass, AuthenticationService hashes the password and prepares the data for database entry.

7

AuthenticationService sends the validated and processed data to the Database to create a new user record.

8

Database attempts to create a new record:

- Checks for uniqueness constraints again (to prevent race conditions).

- If successful, confirms the creation of the user account.

- If it fails (e.g., due to a username now being taken), it sends a failure message back to the AuthenticationService.

9

AuthenticationService receives the response from the Database:

- If the account creation is successful, it sends a success notification to the User Interface.

- If the account creation fails, it sends the appropriate error message to the User Interface.

10

User Interface receives the final response and informs the User:

- Displays a success message and possibly directs the user to a login page or a confirmation email is sent.

- Displays an error message if the registration failed, asking the user to try different credentials or contact support.

(U1) Activity Diagram

ActivityDiagramU1.jpg

Step

Description

1

Open the register account page.

2

Users will be prompted to enter basic information such as email, password, username, and other details.

3

The system will verify the email address entered by the user.

4

If the email exists, the user can go to the next step.

5

If not, the system will go back to the register account day.

6

The system will ask the user whether they agree to our terms of use.

7

If the user agrees to the terms, account registration will be completed.

8

If the user does not agree to the sales, registration will fail and return to the register account day.

Use Case "Log In" (U2)

(U2) Class Diagram

ClassDiagramU2_1.png

Class

Attributes

Methods

Associations

User

UserName: String


Password: String


Email: String


IsAdmin: Boolean

None

- 1 to * with Admin


- 1 to * with Student


- 1 to 1 with UserService

Student

StudentId: int

None

- 1 to 1 with User

Admin

None

None

- 1 to 1 with User

RegisterWindowViewModel

Email: String


Password: String


Username: String


UserService: IUserService

RegisterCommand(): void

- 1 to 1 with IUserService

IRegisterWindowViewModel

None

None

- 1 to 1 with RegisterWindowViewModel

RegisterWindow

None

RegisterWindow(): void


InitializeComponents(): void

- 1 to 1 with Window

Window

None

None

- 1 to 1 with RegisterWindow

IUserService

None

Login(key: String, password: String): Boolean


Register(user: User): Boolean


Delete(): Boolean


ResetPassword(): Boolean

- 1 to 1 with UserService

UserService

Logger: ILogger


MessageBoxService: IMessageBoxService


DatabaseService: IDatabaseService


User: User

Login(key: String, password: String): Boolean


Register(user: User): Boolean


Delete(): Boolean


ResetPassword(): Boolean

- 1 to 1 with IUserService


- 1 to 1 with ILogger


- 1 to 1 with MessageBoxService


- 1 to 1 with IDatabaseService


- 1 to 1 with User

IMessageBoxService

None

MessageBox(title: String, content: String, icon: Icon): void


ErrorMessageBox(title: String, exception: Exception, icon: Icon): void

- 1 to 1 with MessageBoxService

MessageBoxService

MessageBoxTitle: String


Message: String


Exception: Exception


Icon: Icon

MessageBox(title: String, content: String, icon: Icon): void


ErrorMessageBox(title: String, exception: Exception, icon: Icon): void

- 1 to 1 with IMessageBoxService

IDatabaseService

None

SaveUser(user: User): Boolean


GetAllThreadsFromDatabase(): Thread[]


DeleteThread(thread: Thread): Boolean


GetAggregatedDataAsync(): void


GetUsersFromDatabase(): User[]


GetThreadFromId(threadId: int): Thread


SaveCourseInformation(course: CourseInformation): Boolean


GetCourseInformationFromName(courseName: String): CourseInformation


GetDataForAnalysisAsync(): void


GetUserFromKey(key: String): User


SaveThread(thread: Thread): Boolean

- 1 to 1 with UserService


- 1 to 1 with DatabaseService

DatabaseService

Logger: ILogger

SaveUser(user: User): Boolean


GetAllThreadsFromDatabase(): Thread[]


DeleteThread(thread: Thread): Boolean


GetAggregatedDataAsync(): void


GetUsersFromDatabase(): User[]


GetThreadFromId(threadId: int): Thread


SaveCourseInformation(course: CourseInformation): Boolean


GetCourseInformationFromName(courseName: String): CourseInformation


GetDataForAnalysisAsync(): void


GetUserFromKey(key: String): User


SaveThread(thread: Thread): Boolean

- 1 to 1 with IDatabaseService


- 1 to 1 with ILogger

ILogger

None

None

- 1 to 1 with UserService


- 1 to 1 with DatabaseService

ObservableValidator

None

None

- 1 to 1 with RegisterWindowViewModel

ViewModelBase

None

None

- 1 to 1 with RegisterWindowViewModel

(U2) Sequence Diagram

SequenceDiagramU2.png

Actor: User

System Components: User Interface, AuthenticationService, Database

Step

Description

1

User accesses the login form on the User Interface.

2

User enters their username and password into the form.

3

User Interface sends the login credentials to the AuthenticationService.

4

AuthenticationService receives the credentials and performs initial checks:


- Validates the format of the username and password.


- If the format is incorrect, it sends an error message back to the User Interface.

5

If the formats are correct, AuthenticationService hashes the password and sends the username and hashed password to the Database for verification.

6

Database checks the hashed password against the stored hash for the given username:

- If the username does not exist, it returns a "user not found" response.

- If the password does not match, it returns a "wrong password" response.

- If both match, it returns a "login successful" response along with user data if necessary.

7

AuthenticationService receives the response from the Database:

- If the login is successful, it may generate a session token or other security credentials and sends a success message along with any user data to the User Interface.

- If the login fails, it sends the appropriate error message (e.g., "wrong username or password") to the UserInterface.

8

User Interface receives the final response and informs the User:

- Displays a welcome message and transitions the user to the dashboard or homepage if login is successful.

- Displays an error message if the login failed, offering the user the option to try again or reset their password.

(U2) Activity Diagram

ActivityDiagramU2.png

Step

Description

1

Open the Login page

2

The user enters a username and password

3

Press the confirm button

4

The system checks the username first

5

If the username is correct, next check the password

6

If not, the system returns “User not found”, and the system will return to the Login page

7

If the password is correct, the user successfully logs in

8

If not, the system returns “Wrong password”, and the system will return to the Login page

Use Case "View and Edit Account Information" (U3)

(U3) Class Diagram

ClassDiagramU3_1.png

Class

Attributes

Methods

Associations

User

UserName: String


Password: String


Email: String


IsAdmin: Boolean

None

- 1 to * with Admin


- 1 to * with Student


- 1 to 1 with UserService

Student

StudentId: int

None

- 1 to 1 with User

Admin

None

None

- 1 to 1 with User

AccountPageViewModel

User: User


UserService: IUserService

DeleteAccountCommand(): void


ResetPasswordCommand(): void

- 1 to 1 with IUserService


- 1 to 1 with User

IAccountPageViewModel

None

None

- 1 to 1 with AccountPageViewModel

AccountPage

None

AccountPage(): void


InitializeComponents(): void

- 1 to 1 with UserControl

UserControl

None

None

- 1 to 1 with AccountPage

IUserService

None

Login(key: String, password: String): Boolean


Register(user: User): Boolean


Delete(): Boolean


ResetPassword(): Boolean

- 1 to 1 with UserService

UserService

Logger: ILogger


MessageBoxService: IMessageBoxService


DatabaseService: IDatabaseService


User: User

Login(key: String, password: String): Boolean


Register(user: User): Boolean


Delete(): Boolean


ResetPassword(): Boolean

- 1 to 1 with IUserService


- 1 to 1 with ILogger


- 1 to 1 with MessageBoxService


- 1 to 1 with IDatabaseService


- 1 to 1 with User

IMessageBoxService

None

MessageBox(title: String, content: String, icon: Icon): void


ErrorMessageBox(title: String, exception: Exception, icon: Icon): void

- 1 to 1 with MessageBoxService

MessageBoxService

MessageBoxTitle: String


Message: String


Exception: Exception


Icon: Icon

MessageBox(title: String, content: String, icon: Icon): void


ErrorMessageBox(title: String, exception: Exception, icon: Icon): void

- 1 to 1 with IMessageBoxService

IDatabaseService

None

SaveUser(user: User): Boolean


GetAllThreadsFromDatabase(): Thread[]


DeleteThread(thread: Thread): Boolean


GetAggregatedDataAsync(): void


GetUsersFromDatabase(): User[]


GetThreadFromId(threadId: int): Thread


SaveCourseInformation(course: CourseInformation): Boolean


GetCourseInformationFromName(courseName: String): CourseInformation


GetDataForAnalysisAsync(): void


GetUserFromKey(key: String): User


SaveThread(thread: Thread): Boolean

- 1 to 1 with UserService


- 1 to 1 with DatabaseService

DatabaseService

Logger: ILogger

SaveUser(user: User): Boolean


GetAllThreadsFromDatabase(): Thread[]


DeleteThread(thread: Thread): Boolean


GetAggregatedDataAsync(): void


GetUsersFromDatabase(): User[]


GetThreadFromId(threadId: int): Thread


SaveCourseInformation(course: CourseInformation): Boolean


GetCourseInformationFromName(courseName: String): CourseInformation


GetDataForAnalysisAsync(): void


GetUserFromKey(key: String): User


SaveThread(thread: Thread): Boolean

- 1 to 1 with IDatabaseService


- 1 to 1 with ILogger

ILogger

None

None

- 1 to 1 with UserService


- 1 to 1 with DatabaseService

(U3) Sequence Diagram

SequenceDiagramU3.png

Actor: User

System Components: User Interface, UserProfile, Database

Viewing Account Information

Step

Description

1

User logs into the system and navigates to the account information page.

2

User Interface sends a request to UserProfile to retrieve the user's information.

3

UserProfile sends a query to the Database to fetch the user's details.

4

Database retrieves the information and returns it to UserProfile.

5

UserProfile receives the data and sends it to the User Interface.

6

User Interface displays the user's account information (e.g., username, email, name, academic level).

Editing Account Information

Step

Description

1

User selects the option to edit their account information on the same page.

2

User Interface allows the user to edit fields such as email, name, and academic level.

3

User makes changes and submits the updated information.

4

User Interface sends the updated details to UserProfile.

5

UserProfile validates the new information and sends an update request to the Database:

- Checks for the format of the email.

- Validates that the name does not contain invalid characters.

- Ensures that the academic level is within the allowed range.

6

Database updates the user's information and confirms the update back to UserProfile.

7

UserProfile receives the confirmation and notifies the User Interface of the successful update.

8

User Interface informs the User that their information has been successfully updated.

(U3) Activity Diagram

ActivtyDiagramU3.1.png

Step

Description

1

Users need to log into their account.

2

After logging in, users can access their account information.

3

Users can view their current account information.

4

The system prompts users to decide whether they want to edit their information.

5

If users choose to edit, they can input new or updated information.

6

The system saves the changes made by the user.

7

The system confirms the changes to the user.

8

If users do not choose to edit, the process ends without making any changes.

Use Case "Reset Account Password" (U4)

(U4) Class Diagram

ClassDiagramU4_1.png

Class

Attributes

Methods

Associations

User

UserName: String


Password: String


Email: String


IsAdmin: Boolean

None

- 1 to * with Admin


- 1 to * with Student


- 1 to 1 with UserService

Student

StudentId: int

None

- 1 to 1 with User

Admin

None

None

- 1 to 1 with User

AccountPageViewModel

User: User


UserService: IUserService

DeleteAccountCommand(): void


ResetPasswordCommand(): void

- 1 to 1 with IUserService


- 1 to 1 with User

IAccountPageViewModel

None

None

- 1 to 1 with AccountPageViewModel

AccountPage

None

AccountPage(): void


InitializeComponents(): void

- 1 to 1 with UserControl

UserControl

None

None

- 1 to 1 with AccountPage

IUserService

None

Login(key: String, password: String): Boolean


Register(user: User): Boolean


Delete(): Boolean


ResetPassword(): Boolean

- 1 to 1 with UserService

UserService

Logger: ILogger


MessageBoxService: IMessageBoxService


DatabaseService: IDatabaseService


User: User

Login(key: String, password: String): Boolean


Register(user: User): Boolean


Delete(): Boolean


ResetPassword(): Boolean

- 1 to 1 with IUserService


- 1 to 1 with ILogger


- 1 to 1 with MessageBoxService


- 1 to 1 with IDatabaseService


- 1 to 1 with User

IMessageBoxService

None

MessageBox(title: String, content: String, icon: Icon): void


ErrorMessageBox(title: String, exception: Exception, icon: Icon): void

- 1 to 1 with MessageBoxService

MessageBoxService

MessageBoxTitle: String


Message: String


Exception: Exception


Icon: Icon

MessageBox(title: String, content: String, icon: Icon): void


ErrorMessageBox(title: String, exception: Exception, icon: Icon): void

- 1 to 1 with IMessageBoxService

IDatabaseService

None

SaveUser(user: User): Boolean


GetAllThreadsFromDatabase(): Thread[]


DeleteThread(thread: Thread): Boolean


GetAggregatedDataAsync(): void


GetUsersFromDatabase(): User[]


GetThreadFromId(threadId: int): Thread


SaveCourseInformation(course: CourseInformation): Boolean


GetCourseInformationFromName(courseName: String): CourseInformation


GetDataForAnalysisAsync(): void


GetUserFromKey(key: String): User


SaveThread(thread: Thread): Boolean

- 1 to 1 with UserService


- 1 to 1 with DatabaseService

DatabaseService

Logger: ILogger

SaveUser(user: User): Boolean


GetAllThreadsFromDatabase(): Thread[]


DeleteThread(thread: Thread): Boolean


GetAggregatedDataAsync(): void


GetUsersFromDatabase(): User[]


GetThreadFromId(threadId: int): Thread


SaveCourseInformation(course: CourseInformation): Boolean


GetCourseInformationFromName(courseName: String): CourseInformation


GetDataForAnalysisAsync(): void


GetUserFromKey(key: String): User


SaveThread(thread: Thread): Boolean

- 1 to 1 with IDatabaseService


- 1 to 1 with ILogger

ILogger

None

None

- 1 to 1 with UserService


- 1 to 1 with DatabaseService

ObservableValidator

None

None

- 1 to 1 with AccountPageViewModel

ViewModelBase

None

None

- 1 to 1 with AccountPageViewModel

(U4) Sequence Diagram

SequenceDiagramU4.png

Actor: User

System Components: User Interface, AuthenticationService, Database

Step

Description

1

User navigates to the login page and clicks on the "Forgot Password" link.

2

User Interface prompts the User to enter their email address.

3

User enters their email and submits the request.

4

User Interface sends the email address to AuthenticationService.

5

AuthenticationService validates the email format:

- If invalid, it sends an error message back to the User Interface, which then displays it to the User.

6

If the email format is valid, AuthenticationService checks with the Database to confirm the existence of

the account associated with the email.

7

Database returns a response:

- If no account is associated, it sends a "no account found" response to AuthenticationService.

- If found, it sends a "user verified" response.

8

AuthenticationService:

- If the user is verified, it generates a password reset link with a unique, time-limited token.

- Sends the reset link to the User's email.

9

User receives the email and clicks on the password reset link, which redirects them to a password reset

page.

10

User Interface displays the password reset form where the User can enter a new password.

11

User enters a new password and submits the form.

12

User Interface sends the new password to AuthenticationService.

13

AuthenticationService validates the new password against security criteria:

- If the password does not meet the criteria, sends an error message back to the User Interface.

- If it meets the criteria, hashes the password and sends it to the Database for updating.

14

Database updates the password and confirms the update to AuthenticationService.

15

AuthenticationService notifies the User Interface of the successful password reset.

16

User Interface informs the User that their password has been successfully reset and redirects them to the

login page.

(U4) Activity Diagram

ActivityDiagramU4.jpg

Step

Description

1

Open the forgot password page.

2

The user can enter an email address or username to connect the account.

3

The system will confirm whether the account exists.

4

If the account does not exist, the system will return to the beginning.

5

If the account exists, the system will send a password reset link to the user’s email address. The password

reset link will be valid for one hour.

6

If the user enters it in time, then they can reset the password.

7

If not, the user will not be able to reset the password and will go back to the forgot password page.

8

After resetting the password, the system will show the confirm password reset message.

Use Case "Delete Account" (U5)

(U5) Class Diagram

ClassDiagramU5_1.png

Class

Attributes

Methods

Associations

User

UserName: String


Password: String


Email: String


IsAdmin: Boolean

None

- 1 to * with Admin


- 1 to * with Student


- 1 to 1 with UserService

Student

StudentId: int

None

- 1 to 1 with User

Admin

None

None

- 1 to 1 with User

AccountPageViewModel

User: User


UserService: IUserService

DeleteAccountCommand(): void


ResetPasswordCommand(): void

- 1 to 1 with IUserService


- 1 to 1 with User

IAccountPageViewModel

None

None

- 1 to 1 with AccountPageViewModel

AccountPage

None

AccountPage(): void


InitializeComponents(): void

- 1 to 1 with UserControl

UserControl

None

None

- 1 to 1 with AccountPage

IUserService

None

Login(key: String, password: String): Boolean


Register(user: User): Boolean


Delete(): Boolean


ResetPassword(): Boolean

- 1 to 1 with UserService

UserService

Logger: ILogger


MessageBoxService: IMessageBoxService


DatabaseService: IDatabaseService


User: User

Login(key: String, password: String): Boolean


Register(user: User): Boolean


Delete(): Boolean


ResetPassword(): Boolean

- 1 to 1 with IUserService


- 1 to 1 with ILogger


- 1 to 1 with MessageBoxService


- 1 to 1 with IDatabaseService


- 1 to 1 with User

IMessageBoxService

None

MessageBox(title: String, content: String, icon: Icon): void


ErrorMessageBox(title: String, exception: Exception, icon: Icon): void

- 1 to 1 with MessageBoxService

MessageBoxService

MessageBoxTitle: String


Message: String


Exception: Exception


Icon: Icon

MessageBox(title: String, content: String, icon: Icon): void


ErrorMessageBox(title: String, exception: Exception, icon: Icon): void

- 1 to 1 with IMessageBoxService

IDatabaseService

None

SaveUser(user: User): Boolean


GetAllThreadsFromDatabase(): Thread[]


DeleteThread(thread: Thread): Boolean


GetAggregatedDataAsync(): void


GetUsersFromDatabase(): User[]


GetThreadFromId(threadId: int): Thread


SaveCourseInformation(course: CourseInformation): Boolean


GetCourseInformationFromName(courseName: String): CourseInformation


GetDataForAnalysisAsync(): void


GetUserFromKey(key: String): User


SaveThread(thread: Thread): Boolean

- 1 to 1 with UserService


- 1 to 1 with DatabaseService

DatabaseService

Logger: ILogger

SaveUser(user: User): Boolean


GetAllThreadsFromDatabase(): Thread[]


DeleteThread(thread: Thread): Boolean


GetAggregatedDataAsync(): void


GetUsersFromDatabase(): User[]


GetThreadFromId(threadId: int): Thread


SaveCourseInformation(course: CourseInformation): Boolean


GetCourseInformationFromName(courseName: String): CourseInformation


GetDataForAnalysisAsync(): void


GetUserFromKey(key: String): User


SaveThread(thread: Thread): Boolean

- 1 to 1 with IDatabaseService


- 1 to 1 with ILogger

ILogger

None

None

- 1 to 1 with UserService


- 1 to 1 with DatabaseService

ObservableValidator

None

None

- 1 to 1 with AccountPageViewModel

ViewModelBase

None

None

- 1 to 1 with AccountPageViewModel

(U5) Sequence Diagram

SequenceDiagramU5.png

Actor: User

System Components: User Interface, AuthenticationService, Database

Step

Description

1

User logs into the system and navigates to the account settings or profile page.

2

User selects the option to delete their account.

3

User Interface prompts the User to confirm their decision:

- This may include entering their password again for verification and clicking a "Confirm Deletion" button.

4

User enters their password and confirms the deletion.

5

User Interface sends the password and deletion request to AuthenticationService.

6

AuthenticationService verifies the password with the Database:

- If the password is incorrect, it sends an "invalid password" response to the User Interface, which informs the

User.

- If the password is correct, it proceeds with the deletion process.

7

AuthenticationService sends a command to the Database to delete the user's account.

8

Database performs the deletion:

- Removes all records associated with the user's account (personal information, settings, data, etc.).

- Confirms the deletion to AuthenticationService.

9

AuthenticationService receives confirmation of the deletion.

10

AuthenticationService informs the User Interface that the account has been successfully deleted.

11

User Interface notifies the User that their account has been deleted and logs them out of the system.

(U5) Activity Diagram

ActivityDiagramU5.png

Step

Description

1

Opens the user page

2

Press the button to delete the account

3

The user needs to confirm again whether to delete the account

4

If the user presses cancel, the system will return to the user page

5

If the user confirms, the account will be deleted

Use Case "View Academic Calendar" (U6)

(U6) Class Diagram

ClassDiagramU6_1.png

Class

Attributes

Methods

Associations

HomePageViewModel

IsAdvancedSearch: Boolean


SearchText: String


Courses: CourseInformation[]


OpenAIService: IOpenAIService


MessageBoxService: IMessageBoxService


DatabaseService: IDatabaseService

HomePageViewModel()


OpenAcademicCalendarCommand(): void


AdvancedSearchCommand(): void

- 1 to 1 with IOpenAIService


- 1 to 1 with IDatabaseService


- 1 to 1 with IMessageBoxService


- 1 to 1 with ViewModelBase

IHomePageViewModel

None

None

- 1 to 1 with HomePageViewModel

ViewModelBase

None

None

- 1 to 1 with HomePageViewModel

ObservableValidator

None

None

- 1 to 1 with HomePageViewModel

IOpenAIService

None

AnalyzeText(text: String): String

- 1 to 1 with OpenAIService

OpenAIService

Logger: ILogger

AnalyzeText(text: String): String

- 1 to 1 with IOpenAIService


- 1 to 1 with ILogger

ILogger

None

None

- 1 to 1 with OpenAIService


- 1 to 1 with DatabaseService

IDatabaseService

None

GetUsersFromDatabase(): User[]


GetUserFromKey(key: String): User


GetCourseInformationFromName(courseName: String): CourseInformation


GetAllThreadsFromDatabase(): Thread[]


GetThreadFromId(threadId: int): Thread


SaveUser(user: User): Boolean


SaveCourseInformation(course: CourseInformation): Boolean


SaveThread(thread: Thread): Boolean


DeleteThread(thread: Thread): Boolean


GetAggregatedDataAsync(): void


GetDataForAnalysisAsync(): void

- 1 to 1 with HomePageViewModel


- 1 to 1 with DatabaseService

DatabaseService

Logger: ILogger

GetUsersFromDatabase(): User[]


GetUserFromKey(key: String): User


GetCourseInformationFromName(courseName: String): CourseInformation


GetAllThreadsFromDatabase(): Thread[]


GetThreadFromId(threadId: int): Thread


SaveUser(user: User): Boolean


SaveCourseInformation(course: CourseInformation): Boolean


SaveThread(thread: Thread): Boolean


DeleteThread(thread: Thread): Boolean


GetAggregatedDataAsync(): void


GetDataForAnalysisAsync(): void

- 1 to 1 with IDatabaseService


- 1 to 1 with ILogger

IMessageBoxService

None

MessageBox(title: String, content: String, icon: Icon): void


ErrorMessageBox(title: String, exception: Exception, icon: Icon): void

- 1 to 1 with MessageBoxService

MessageBoxService

MessageBoxTitle: String


Message: String


Exception: Exception


Icon: Icon

MessageBox(title: String, content: String, icon: Icon): void


ErrorMessageBox(title: String, exception: Exception, icon: Icon): void

- 1 to 1 with IMessageBoxService

HomePage

None

HomePage(): void


InitializeComponents(): void

- 1 to 1 with UserControl

UserControl

None

None

- 1 to 1 with HomePage

(U6) Sequence Diagram

SequenceDiagram6.png

Actor: User

System Components: User Interface, System, Database

Step

Description

1

User logs into the system and navigates to the section where the academic calendar is available.

2

User Interface sends a request to the System to retrieve the academic calendar.

3

System sends a query to the Database to fetch the academic calendar data.

4

Database retrieves the calendar details and sends them back to the System.

5

System processes the calendar data, organizing it into a user-friendly format.

6

System sends the formatted academic calendar to the User Interface.

7

User Interface displays the academic calendar to the User, allowing them to view important academic dates, such as semester start and end dates, exam periods, holidays, and registration deadlines.

(U6) Activity Diagram

ActivityDiagramU6.png

Step

Description

1

User requests to view academic calendar.

2

System gets academic calendar data.

3

System displays academic calendar.

Use Case "View and Bookmark Course Pathways" (U7)

(U7) Class Diagram

ClassDiagramU7_1.jpg

Class

Attributes

Methods

Associations

User

UserName: String


Password: String


Email: String


IsAdmin: Boolean

None

- * to 1 with CourseInformation


- 1 to 1 with UserService


- 1 to 1 with CoursePageViewModel


- 1 to 1 with IDatabaseService

Student

StudentId: int

None

- 1 to 1 with User

Admin

None

None

- 1 to * with User

CourseInformation

Id: int


Name: String


Description: String


Credits: int


Prerequisites: CourseInformation[]


Thread: Thread


IsBookmarked: Boolean


Category: CourseCategory


Rating: CourseRating

None

- 1 to * with User


- 1 to 1 with IDatabaseService

CoursePageViewModel

CourseService: ICourseService


Courses: CourseInformation[]

AddBookmarkCommand(): void


RemoveBookmarkCommand(): void

- 1 to 1 with ICourseService


- 1 to 1 with User

ICoursePageViewModel

None

None

- 1 to 1 with CoursePageViewModel

ICourseService

None

AddBookmark(course: CourseInformation): Boolean


RemoveBookmark(course: CourseInformation): Boolean


GetCourseDetails(course: CourseInformation): String


SubmitCourseFeedback(course: CourseInformation): Boolean

- 1 to 1 with CourseService


- 1 to 1 with CoursePageViewModel

CourseService

Logger: ILogger


MessageBoxService: IMessageBoxService


DatabaseService: IDatabaseService


User: User

AddBookmark(course: CourseInformation): Boolean


RemoveBookmark(course: CourseInformation): Boolean


GetCourseDetails(course: CourseInformation): String


SubmitCourseFeedback(course: CourseInformation): Boolean

- 1 to 1 with ICourseService


- 1 to 1 with ILogger


- 1 to 1 with MessageBoxService


- 1 to 1 with IDatabaseService


- 1 to 1 with CourseInformation


- 1 to 1 with User

ILogger

None

None

- 1 to 1 with CourseService


- 1 to 1 with UserService

IMessageBoxService

None

ErrorMessageBox(title: String, message: String, exception: Exception, icon: Icon): void

- 1 to 1 with CourseService


- 1 to 1 with UserService

MessageBoxService

MessageBoxTitle: String


Message: String


Exception: Exception


Icon: Icon

ErrorMessageBox(title: String, message: String, exception: Exception, icon: Icon): void

- 1 to 1 with CourseService


- 1 to 1 with UserService

IDatabaseService

None

SaveUser(user: User): Boolean


GetAllThreadsFromDatabase(): Thread[]


DeleteThread(thread: Thread): Boolean


GetAggregatedDataAsync(): void


GetUsersFromDatabase(): User[]


GetThreadFromId(threadId: int): Thread


SaveCourseInformation(course: CourseInformation): Boolean


GetCourseInformationFromName(courseName: String): CourseInformation


GetDataForAnalysisAsync(): void


GetUserFromKey(key: String): User


SaveThread(thread: Thread): Boolean

- 1 to 1 with CourseService


- 1 to 1 with DatabaseService

DatabaseService

Logger: ILogger

SaveUser(user: User): Boolean


GetAllThreadsFromDatabase(): Thread[]


DeleteThread(thread: Thread): Boolean


GetAggregatedDataAsync(): void


GetUsersFromDatabase(): User[]


GetThreadFromId(threadId: int): Thread


SaveCourseInformation(course: CourseInformation): Boolean


GetCourseInformationFromName(courseName: String): CourseInformation


GetDataForAnalysisAsync(): void


GetUserFromKey(key: String): User


SaveThread(thread: Thread): Boolean

- 1 to 1 with IDatabaseService


- 1 to 1 with ILogger

ObservableValidator

None

None

- 1 to 1 with CoursePageViewModel

ViewModelBase

None

None

- 1 to 1 with CoursePageViewModel

UserControl

None

None

- 1 to 1 with CoursePage

CoursePage

None

CoursePage(): void


InitializeComponents(): void

- 1 to 1 with UserControl

CourseCategory

NAME(): String

None

- Enumeration used by CourseInformation

CourseRating

NAME(): String

None

- Enumeration used by CourseInformation

(U7) Sequence Diagram

SequenceDiagramU7.png

Actor: User

System Components: User Interface, Course, CourseBookmark, Database

Viewing Course Pathways

Step

Description

1

User logs into the system and navigates to the section where course pathways are available.

2

User Interface sends a request to the Course component to retrieve the available courses and their pathways.

3

Course component queries the Database to fetch the course details and pathways.

4

Database returns the requested course data to the Course component.

5

Course component formats the course data and sends it back to the User Interface.

6

User Interface displays the course pathways to the User, allowing them to explore various courses and their prerequisites, credits, and descriptions.

Bookmarking Courses

Step

Description

1

User selects specific courses they are interested in and chooses to bookmark them for future reference.

2

User Interface captures the user's selection and sends the course IDs to the CourseBookmark component.

3

CourseBookmark component processes the request and sends it to the Database to save the bookmarks under the user’s profile.

4

Database stores the bookmark details and confirms the successful bookmarking back to the CourseBookmark component.

5

CourseBookmark component confirms the successful bookmarking to the User Interface.

6

User Interface notifies the User that the courses have been successfully bookmarked.

(U7) Activity Diagram

ActivityDiagramU7.png

Step

Description

1

User views recommended courses.

2

User selects a course to bookmark.

3

System saves the course to the bookmark list.

4

User accesses the bookmark section.

5

System displays bookmarked courses.

6

If the user removes a course from the bookmark, the system returns to the viewing recommended courses page.

7

If the user adds courses to the bookmark, the system updates the bookmark list.

Use Case "Filter Courses" (U8)

(U8) Class Diagram

ClassDiagramU8_1.png

Class

Attributes

Methods

Associations

User

UserName: String


Password: String


Email: String


IsAdmin: Boolean

None

- * to 1 with CourseInformation


- * to 1 with DatabaseService


- 1 to 1 with HomePageViewModel


- 1 to 1 with UserService


CourseInformation

Id: int


Name: String


Description: String


Credits: int


Prerequisites: CourseInformation[]


Thread: Thread


IsBookmarked: Boolean


Category: CourseCategory


Rating: CourseRating

None

- 1 to * with User


- 1 to 1 with IDatabaseService


- 1 to 1 with HomePageViewModel

HomePageViewModel

IsAdvancedSearch: Boolean


SearchText: String


Courses: CourseInformation[]


OpenAIService: IOpenAIService


MessageBoxService: IMessageBoxService


DatabaseService: IDatabaseService

HomePageViewModel(): void


OpenAcademicCalendarCommand(): void


AdvancedSearchCommand(): void

- 1 to 1 with ICourseInformation


- 1 to 1 with IOpenAIService


- 1 to 1 with IDatabaseService


- 1 to 1 with IMessageBoxService


- 1 to 1 with IHomePageViewModel

IHomePageViewModel

None

None

- 1 to 1 with HomePageViewModel

IDatabaseService

None

SaveUser(user: User): Boolean


GetAllThreadsFromDatabase(): Thread[]


DeleteThread(thread: Thread): Boolean


GetAggregatedDataAsync(): void


GetUsersFromDatabase(): User[]


GetThreadFromId(threadId: int): Thread


SaveCourseInformation(course: CourseInformation): Boolean


GetCourseInformationFromName(courseName: String): CourseInformation


GetDataForAnalysisAsync(): void


GetUserFromKey(key: String): User


SaveThread(thread: Thread): Boolean

- 1 to 1 with HomePageViewModel


- 1 to 1 with DatabaseService

DatabaseService

Logger: ILogger

SaveUser(user: User): Boolean


GetAllThreadsFromDatabase(): Thread[]


DeleteThread(thread: Thread): Boolean


GetAggregatedDataAsync(): void


GetUsersFromDatabase(): User[]


GetThreadFromId(threadId: int): Thread


SaveCourseInformation(course: CourseInformation): Boolean


GetCourseInformationFromName(courseName: String): CourseInformation


GetDataForAnalysisAsync(): void


GetUserFromKey(key: String): User


SaveThread(thread: Thread): Boolean

- 1 to 1 with IDatabaseService


- 1 to 1 with ILogger

IOpenAIService

None

AnalyzeText(text: String): String

- 1 to 1 with OpenAIService


- 1 to 1 with HomePageViewModel

OpenAIService

Logger: ILogger

AnalyzeText(text: String): String

- 1 to 1 with IOpenAIService


- 1 to 1 with OpenAIServiceTest


- 1 to 1 with HomePageViewModel

OpenAIServiceTest

None

AnalyzeText_Test(): void

- 1 to 1 with OpenAIService

ILogger

None

None

- 1 to 1 with OpenAIService


- 1 to 1 with DatabaseService


- 1 to 1 with UserService

IMessageBoxService

None

MessageBox(title: String, content: String, icon: Icon): void


ErrorMessageBox(title: String, exception: Exception, icon: Icon): void

- 1 to 1 with MessageBoxService


- 1 to 1 with HomePageViewModel

MessageBoxService

MessageBoxTitle: String


Message: String


Exception: Exception


Icon: Icon

MessageBox(title: String, content: String, icon: Icon): void


ErrorMessageBox(title: String, exception: Exception, icon: Icon): void

- 1 to 1 with IMessageBoxService


- 1 to 1 with HomePageViewModel

CourseCategory

NAME(): String

None

- Enumeration used by CourseInformation

CourseRating

NAME(): String

None

- Enumeration used by CourseInformation

UserControl

None

None

- 1 to 1 with HomePage

HomePage

None

HomePage(): void


InitializeComponents(): void

- 1 to 1 with UserControl

ObservableValidator

None

None

- 1 to 1 with HomePageViewModel

ViewModelBase

None

None

- 1 to 1 with HomePageViewModel

(U8) Sequence Diagram

SequenceDiagramU8.png

Actor: User

System Components: User Interface, CourseRecommendation, Database

Step

Description

1

User accesses the course browsing or recommendation section of the application.

2

User Interface displays various filter options (e.g., department, level, availability).

3

User selects desired filter criteria and submits the filter request.

4

User Interface captures the filter choices and sends them to the CourseRecommendation component.

5

CourseRecommendation processes the request, formulating a query based on the selected criteria.

6

CourseRecommendation sends the query to the Database to retrieve relevant courses.

7

Database executes the query and retrieves courses that match the filter criteria.

8

Database sends the filtered course results back to the CourseRecommendation component.

9

CourseRecommendation processes the results, perhaps ordering or further refining them based on additional logic (like prioritizing by popularity or prerequisites).

10

CourseRecommendation sends the processed course list back to the User Interface.

11

User Interface updates the display to show the filtered courses to the User.

(U8) Activity Diagram

ActivityDiagramU8.png

Step

Description

1

Users select the criteria they want to use to filter courses.

2

The system applies the selected filter criteria.

3

The system retrieves the list of courses that match the filter criteria.

4

Users can view the list of filtered courses.

5

Users can select criteria to sort the filtered courses.

6

The system displays the sorted list of filtered courses.

Use Case "Obtain Course Recommendation from Query" (U9)

(U9) Class Diagram

ClassDiagramU9_1.png

Class

Attributes

Methods

Associations

User

UserName: String


Password: String


Email: String


IsAdmin: Boolean

None

- * to 1 with CourseInformation


- * to 1 with DatabaseService


- 1 to 1 with HomePageViewModel


- 1 to 1 with UserService


CourseInformation

Id: int


Name: String


Description: String


Credits: int


Prerequisites: CourseInformation[]


Thread: Thread


IsBookmarked: Boolean


Category: CourseCategory


Rating: CourseRating

None

- 1 to * with User


- 1 to 1 with IDatabaseService


- 1 to 1 with HomePageViewModel

HomePageViewModel

IsAdvancedSearch: Boolean


SearchText: String


Courses: CourseInformation[]


OpenAIService: IOpenAIService


MessageBoxService: IMessageBoxService


DatabaseService: IDatabaseService

HomePageViewModel(): void


OpenAcademicCalendarCommand(): void


AdvancedSearchCommand(): void

- 1 to 1 with ICourseInformation


- 1 to 1 with IOpenAIService


- 1 to 1 with IDatabaseService


- 1 to 1 with IMessageBoxService


- 1 to 1 with IHomePageViewModel

IHomePageViewModel

None

None

- 1 to 1 with HomePageViewModel

IDatabaseService

None

SaveUser(user: User): Boolean


GetAllThreadsFromDatabase(): Thread[]


DeleteThread(thread: Thread): Boolean


GetAggregatedDataAsync(): void


GetUsersFromDatabase(): User[]


GetThreadFromId(threadId: int): Thread


SaveCourseInformation(course: CourseInformation): Boolean


GetCourseInformationFromName(courseName: String): CourseInformation


GetDataForAnalysisAsync(): void


GetUserFromKey(key: String): User


SaveThread(thread: Thread): Boolean

- 1 to 1 with HomePageViewModel


- 1 to 1 with DatabaseService

DatabaseService

Logger: ILogger

SaveUser(user: User): Boolean


GetAllThreadsFromDatabase(): Thread[]


DeleteThread(thread: Thread): Boolean


GetAggregatedDataAsync(): void


GetUsersFromDatabase(): User[]


GetThreadFromId(threadId: int): Thread


SaveCourseInformation(course: CourseInformation): Boolean


GetCourseInformationFromName(courseName: String): CourseInformation


GetDataForAnalysisAsync(): void


GetUserFromKey(key: String): User


SaveThread(thread: Thread): Boolean

- 1 to 1 with IDatabaseService


- 1 to 1 with ILogger

IOpenAIService

None

AnalyzeText(text: String): String

- 1 to 1 with OpenAIService


- 1 to 1 with HomePageViewModel

OpenAIService

Logger: ILogger

AnalyzeText(text: String): String

- 1 to 1 with IOpenAIService


- 1 to 1 with OpenAIServiceTest


- 1 to 1 with HomePageViewModel

OpenAIServiceTest

None

AnalyzeText_Test(): void

- 1 to 1 with OpenAIService

ILogger

None

None

- 1 to 1 with OpenAIService


- 1 to 1 with DatabaseService


- 1 to 1 with UserService

IMessageBoxService

None

MessageBox(title: String, content: String, icon: Icon): void


ErrorMessageBox(title: String, exception: Exception, icon: Icon): void

- 1 to 1 with MessageBoxService


- 1 to 1 with HomePageViewModel

MessageBoxService

MessageBoxTitle: String


Message: String


Exception: Exception


Icon: Icon

MessageBox(title: String, content: String, icon: Icon): void


ErrorMessageBox(title: String, exception: Exception, icon: Icon): void

- 1 to 1 with IMessageBoxService


- 1 to 1 with HomePageViewModel

CourseCategory

NAME(): String

None

- Enumeration used by CourseInformation

CourseRating

NAME(): String

None

- Enumeration used by CourseInformation

UserControl

None

None

- 1 to 1 with HomePage

HomePage

None

HomePage(): void


InitializeComponents(): void

- 1 to 1 with UserControl

ObservableValidator

None

None

- 1 to 1 with HomePageViewModel

ViewModelBase

None

None

- 1 to 1 with HomePageViewModel

(U9) Sequence Diagram

SequenceDiagramU9.png

Actor: User

System Components: User Interface, Query, OpenAIAPI, CourseRecommendation, Database

Step

Description

1

User logs into the system and navigates to the course recommendation feature.

2

User inputs a natural language query describing their course interests or requirements in the search field provided on the User Interface.

3

User Interface captures the query and sends it to the Query component.

4

Query component parses the query to extract essential keywords and search parameters, then sends this refined data to the OpenAIAPI.

5

OpenAIAPI analyzes the refined query to further understand the context and intent, extracting key topics and terms relevant to courses.

6

OpenAIAPI sends the analysis results back to the Query component.

7

Query component forwards these results to the CourseRecommendation system.

8

CourseRecommendation uses the received keywords and terms to formulate a database search query.

9

CourseRecommendation sends the search query to the Database to find matching courses.

10

Database retrieves courses that fit the criteria and sends them back to the CourseRecommendation system.

11

CourseRecommendation processes the list, possibly ranking the courses based on relevance to the query, popularity, and other criteria.

12

CourseRecommendation sends the final list of recommended courses to the User Interface.

13

User Interface displays the recommended courses to the User, providing detailed information such as course descriptions, prerequisites, and possible pathways.

(U9) Activity Diagram

ActivityDiagramU9.png

Step

Description

1

Users start by inputting their query or requirements for course recommendations.

2

The system processes the user's query.

3

The system generates course recommendations based on the processed query.

4

The system displays the recommended courses to the user.

5

The system asks users if they want to provide feedback on the recommendations.

6

If users choose to provide feedback, the system collects feedback from the user about the recommendations.

7

If users do not choose to provide feedback, the process ends without collecting feedback.

Use Case "Submit Course Feedback" (U10)

(U10) Class Diagram

SubmitCourseFeedback(U10)_ClassDiagram.png

Class

Attributes

Methods

Associations

User

UserName: String


Password: String


Email: String


IsAdmin: Boolean

None

- * to 1 with CourseInformation


- * to 1 with CourseService


- 1 to 1 with UserService


- 1 to 1 with CoursePageViewModel

Student

StudentId: int

None

- 1 to 1 with User

CourseInformation

Id: int


Name: String


Description: String


Credits: int


Prerequisites: CourseInformation[]


Thread: Thread


IsBookmarked: Boolean


Category: CourseCategory


Rating: CourseRating

None

- 1 to * with User


- 1 to 1 with IDatabaseService

CoursePageViewModel

CourseService: ICourseService


Courses: CourseInformation[]

AddBookmarkCommand(): void


RemoveBookmarkCommand(): void

- 1 to 1 with ICourseService


- 1 to 1 with User

ICoursePageViewModel

None

None

- 1 to 1 with CoursePageViewModel

ICourseService

None

AddBookmark(course: CourseInformation): Boolean


RemoveBookmark(course: CourseInformation): Boolean


GetCourseDetails(course: CourseInformation): String


SubmitCourseFeedback(course: CourseInformation): Boolean

- 1 to 1 with CourseService


- 1 to 1 with CoursePageViewModel

CourseService

Logger: ILogger


MessageBoxService: IMessageBoxService


DatabaseService: IDatabaseService


User: User

AddBookmark(course: CourseInformation): Boolean


RemoveBookmark(course: CourseInformation): Boolean


GetCourseDetails(course: CourseInformation): String


SubmitCourseFeedback(course: CourseInformation): Boolean

- 1 to 1 with ICourseService


- 1 to 1 with ILogger


- 1 to 1 with MessageBoxService


- 1 to 1 with IDatabaseService


- 1 to 1 with CourseInformation


- 1 to 1 with User

IUserService

None

Login(key: String, password: String): Boolean


Register(user: User): Boolean


Delete(): Boolean


ResetPassword(): Boolean

- 1 to 1 with UserService


- 1 to 1 with User

UserService

Logger: ILogger


MessageBoxService: IMessageBoxService


DatabaseService: IDatabaseService


User: User

Login(key: String, password: String): Boolean


Register(user: User): Boolean


Delete(): Boolean


ResetPassword(): Boolean

- 1 to 1 with IUserService


- 1 to 1 with ILogger


- 1 to 1 with MessageBoxService


- 1 to 1 with IDatabaseService


- 1 to 1 with CoursePageViewModel

ILogger

None

None

- 1 to 1 with CourseService


- 1 to 1 with UserService

IDatabaseService

None

DeleteThread(thread: Thread): Boolean


SaveCourseInformation(course: CourseInformation): Boolean


GetUsersFromDatabase(): User[]


GetUserFromKey(key: String): User


GetThreadFromId(threadId: int): Thread


SaveUser(user: User): Boolean


GetDataForAnalysis(): void


SaveThread(thread: Thread): Boolean


GetThreadsFromDatabase(): Thread[]


GetAllThreadsFromDatabase(): Thread[]


GetCourseInformationFromName(courseName: String): CourseInformation

- 1 to 1 with CourseService


- 1 to 1 with DatabaseService

DatabaseService

Logger: ILogger

DeleteThread(thread: Thread): Boolean


SaveCourseInformation(course: CourseInformation): Boolean


GetUsersFromDatabase(): User[]


GetUserFromKey(key: String): User


GetThreadFromId(threadId: int): Thread


SaveUser(user: User): Boolean


GetDataForAnalysis(): void


SaveThread(thread: Thread): Boolean


GetThreadsFromDatabase(): Thread[]


GetAllThreadsFromDatabase(): Thread[]


GetCourseInformationFromName(courseName: String): CourseInformation

- 1 to 1 with IDatabaseService


- 1 to 1 with ILogger

ObservableValidator

None

None

- 1 to 1 with CoursePageViewModel

ViewModelBase

None

None

- 1 to 1 with CoursePageViewModel

UserControl

None

None

- 1 to 1 with CoursePage

CoursePage

None

CoursePage(): void


InitializeComponents(): void

- 1 to 1 with UserControl

(U10) Sequence Diagram

SequenceDiagramU10.png

Actor: User

System Components: User Interface, Feedback, Database

Step

Description

1

User completes a course and decides to provide feedback.

2

User navigates to the feedback section of the course in the User Interface.

3

User Interface provides a form for submitting feedback, which includes rating and comment fields.

4

User fills out the form, providing a numerical rating and optional textual comments.

5

User Interface captures the feedback and sends it to the Feedback component.

6

Feedback component validates the input to ensure it meets any specified criteria (e.g., rating within valid range, comments do not contain prohibited content).

7

If validation fails, Feedback component sends an error message back to the User Interface, which then displays it to the User.

8

If validation passes, Feedback component sends the feedback data to the Database.

9

Database stores the feedback, linking it with the user's ID and the course ID.

10

Database confirms the successful storage of feedback to the Feedback component.

11

Feedback component notifies the User Interface of the successful feedback submission.

12

User Interface displays a confirmation message to the User thanking them for their feedback.

(U10) Activity Diagram

ActivityDiagramU10.png

Step

Description

1

User completes a course.

2

User enters a rating from a scale of 1 to 5.

3

Users have the option to leave written reviews.

4

User submits course feedback.

5

System filters inappropriate language/spam.

6

If feedback is inappropriate, the system goes back to the leave written review page.

7

If feedback is appropriate, the feedback will be stored by the system.

8

System aggregates ratings.

9

System displays ratings and reviews.

Use Case "Access and Analyze User Data" (U11)

(U11) Class Diagram

ClassDiagram(U11)_AccessAndAnalyseUserData.png

Class

Attributes

Methods

Associations

User

UserName: String


Password: String


Email: String


IsAdmin: Boolean

None

- * to 1 with Admin


- 1 to 1 with UserService


- * to 1 with AnalyticsService

Admin

None

None

- * to 1 with User

AdminPageViewModel

AdminService: IAdminService


Analytics: String

ViewAnalyticsCommand(): void

- 1 to 1 with IAdminService


- 1 to 1 with IAdminPageViewModel

IAdminPageViewModel

None

None

- 1 to 1 with AdminPageViewModel

IAdminService

None

Login(key: String, password: String): Boolean


Register(user: User): Boolean


Delete(): Boolean


ResetPassword(): Boolean

- 1 to 1 with AdminPageViewModel

IUserService

None

Login(key: String, password: String): Boolean


Register(user: User): Boolean


Delete(): Boolean


ResetPassword(): Boolean

- 1 to 1 with UserService


- 1 to 1 with User

UserService

Logger: ILogger


MessageBoxService: IMessageBoxService


DatabaseService: IDatabaseService


User: User

Login(key: String, password: String): Boolean


Register(user: User): Boolean


Delete(): Boolean


ResetPassword(): Boolean

- 1 to 1 with IUserService


- 1 to 1 with ILogger


- 1 to 1 with MessageBoxService


- 1 to 1 with IDatabaseService

ILogger

None

None

- 1 to 1 with UserService


- 1 to 1 with AnalyticsService

IDatabaseService

None

DeleteThread(thread: Thread): Boolean


SaveCourseInformation(course: CourseInformation): Boolean


GetUsersFromDatabase(): User[]


GetUserFromKey(key: String): User


GetThreadFromId(threadId: int): Thread


SaveUser(user: User): Boolean


GetDataForAnalysis(): void


SaveThread(thread: Thread): Boolean


GetThreadsFromDatabase(): Thread[]


GetAllThreadsFromDatabase(): Thread[]


GetCourseInformationFromName(courseName: String): CourseInformation

- 1 to 1 with AnalyticsService


- 1 to 1 with DatabaseService

DatabaseService

Logger: ILogger

DeleteThread(thread: Thread): Boolean


SaveCourseInformation(course: CourseInformation): Boolean


GetUsersFromDatabase(): User[]


GetUserFromKey(key: String): User


GetThreadFromId(threadId: int): Thread


SaveUser(user: User): Boolean


GetDataForAnalysis(): void


SaveThread(thread: Thread): Boolean


GetThreadsFromDatabase(): Thread[]


GetAllThreadsFromDatabase(): Thread[]


GetCourseInformationFromName(courseName: String): CourseInformation

- 1 to 1 with IDatabaseService


- 1 to 1 with ILogger

IAnalyticsService

None

AggregateData(): void


FetchDataForAnalysis(): void

- 1 to 1 with AnalyticsService

AnalyticsService

DatabaseService: IDatabaseService


Logger: ILogger

AggregateData(): String


FetchDataForAnalysis(): void

- 1 to 1 with IAnalyticsService


- 1 to 1 with IDatabaseService

ObservableValidator

None

None

- 1 to 1 with AdminPageViewModel

ViewModelBase

None

None

- 1 to 1 with AdminPageViewModel

UserControl

None

None

- 1 to 1 with AdminPage

AdminPage

None

AdminPage(): void


InitializeComponents(): void

- 1 to 1 with UserControl

(U11) Sequence Diagram

SequenceDiagramU11.png

Actor: Admin

System Components: User Interface, SystemAnalytics, Database

Step

Description

1

Admin logs into the system and navigates to the dashboard for user data analysis.

2

User Interface presents options for selecting specific data sets (e.g., user engagement metrics, feedback, course completion rates) and criteria for analysis (e.g., time period, user demographics).

3

Admin selects the desired data sets and criteria, and submits the query.

4

User Interface sends the request to the SystemAnalytics component.

5

SystemAnalytics formulates the query based on the selected parameters and sends it to the Database.

6

Database executes the query and retrieves the relevant user data.

7

Database sends the raw data back to the SystemAnalytics.

8

SystemAnalytics processes the raw data, performing necessary calculations and transformations to produce actionable insights (e.g., statistical analysis, trend detection, pattern recognition).

9

SystemAnalytics sends the analyzed data back to the User Interface.

10

User Interface displays the analyzed results in an accessible format (e.g., graphs, charts, tables) to the Admin.

11

Admin reviews the results, gaining insights into user behavior and system performance which can be used to make informed decisions about system improvements, policy changes, or targeted interventions.

(U11) Activity Diagram

ActivityDiagramU11.jpg

Step

Description

1

University official opens the access user data page.

2

The user selects which data they want to access (User data or Course data).

3

Selecting user data, the user can view user information and user data analyzed by the system.

4

Selecting course data, the user can view course information and course data analyzed by the system.

5

Users end this access.

6

The user can choose to access other data or end visit to the access user data page.

7

If user wants to access other data, the system will return to select data stage.

8

If user wants to end visit, the activity ends.

Use Case "Create and Delete Thread" (U12)

(U12) Class Diagram

CreateAndDeleteThread_ClassDigram(U12)_1.png

Class

Attributes

Methods

Associations

User

UserName: String


Password: String


Email: String


IsAdmin: Boolean

None

- * to 1 with Thread


- 1 to 1 with UserService


- 1 to 1 with ForumPageViewModel

Student

StudentId: int

None

- 1 to 1 with User

Thread

ThreadId: int


Title: String


Creator: User


Description: String


CreationTime: DateTime


Posts: int

None

- * to 1 with User


- 1 to * with CourseInformation

CourseInformation

Category: CourseCategory


Name: String


Description: String


Prerequisites: CourseInformation[]


Credits: int


Rating: CourseRating


IsBookmarked: Boolean


Id: int


Thread: Thread

None

- 1 to * with Thread


- 1 to 1 with IDatabaseService

ForumPageViewModel

ForumService: IForumService

UpvoteCommand(post: Post): Boolean


DownvoteCommand(post: Post): Boolean


ViewThreadCommand(): void


CreateThreadCommand(title: String, description: String): Boolean


DeleteThreadCommand(thread: Thread): Boolean


CreatePostCommand(thread: Thread, post: int): Boolean


EditPostCommand(thread: Thread, post: int): Boolean


ReplyPostCommand(thread: Thread, post: int): Boolean


DeletePostCommand(post: int): Boolean

- 1 to 1 with IForumService


- 1 to 1 with User


- 1 to 1 with IForumPageViewModel

IForumPageViewModel

None

None

- 1 to 1 with ForumPageViewModel

IForumService

None

CreateThread(title: String, description: String): Boolean


GetThreadInformation(threadId: int): Thread


DeleteThread(thread: Thread): Boolean


CreatePost(thread: Thread, post: Post): Boolean


EditPost(thread: Thread, post: int): Boolean


ReplyPost(thread: Thread, post: Post): Boolean


DeletePost(post: int): Boolean

- 1 to 1 with ForumService


- 1 to 1 with ForumPageViewModel

ForumService

ImageService: IImageService


Logger: ILogger


MessageBoxService: IMessageBoxService


UploadService: IUploadService


User: User

CreateThread(title: String, description: String): Boolean


GetThreadInformation(threadId: int): Thread


DeleteThread(thread: Thread): Boolean


CreatePost(thread: Thread, post: Post): Boolean


EditPost(thread: Thread, post: int): Boolean


ReplyPost(thread: Thread, post: Post): Boolean


DeletePost(post: int): Boolean

- 1 to 1 with IForumService


- 1 to 1 with ILogger


- 1 to 1 with MessageBoxService


- 1 to 1 with IDatabaseService


- 1 to 1 with CourseInformation


- 1 to 1 with Thread


- 1 to 1 with Post

IUserService

None

Login(key: String, password: String): Boolean


Register(user: User): Boolean


Delete(): Boolean


ResetPassword(): Boolean

- 1 to 1 with UserService


- 1 to 1 with User

UserService

Logger: ILogger


MessageBoxService: IMessageBoxService


DatabaseService: IDatabaseService


User: User

Login(key: String, password: String): Boolean


Register(user: User): Boolean


Delete(): Boolean


ResetPassword(): Boolean

- 1 to 1 with IUserService


- 1 to 1 with ILogger


- 1 to 1 with MessageBoxService


- 1 to 1 with IDatabaseService

ILogger

None

None

- 1 to 1 with ForumService


- 1 to 1 with UserService

IMessageBoxService

None

ErrorMessageBox(title: String, message: String, exception: Exception, icon: Icon): void

- 1 to 1 with ForumService


- 1 to 1 with UserService

MessageBoxService

MessageBoxTitle: String


Message: String


Exception: Exception


Icon: Icon

ErrorMessageBox(title: String, message: String, exception: Exception, icon: Icon): void

- 1 to 1 with ForumService


- 1 to 1 with UserService

IUploadService

None

Upload(bytes: byte[]): Boolean

- 1 to 1 with ForumService

UploadService

ImageService: IImageService


Upload(bytes: byte[]): Boolean

None

- 1 to 1 with ForumService

IImageService

None

Encode(stream: Stream): Bitmap

- 1 to 1 with ForumService

ImageService

Encode(stream: Stream): Bitmap

None

- 1 to 1 with ForumService

IDatabaseService

None

DeleteThread(thread: Thread): Boolean


SaveCourseInformation(course: CourseInformation): Boolean


GetUsersFromDatabase(): User[]


GetUserFromKey(key: String): User


GetThreadFromId(threadId: int): Thread


SaveUser(user: User): Boolean


GetDataForAnalysis(): void


SaveThread(thread: Thread): Boolean


GetThreadsFromDatabase(): Thread[]


GetAllThreadsFromDatabase(): Thread[]


GetCourseInformationFromName(courseName: String): CourseInformation

- 1 to 1 with ForumService


- 1 to 1 with DatabaseService


- 1 to 1 with ILogger

DatabaseService

Logger: ILogger

DeleteThread(thread: Thread): Boolean


SaveCourseInformation(course: CourseInformation): Boolean


GetUsersFromDatabase(): User[]


GetUserFromKey(key: String): User


GetThreadFromId(threadId: int): Thread


SaveUser(user: User): Boolean


GetDataForAnalysis(): void


SaveThread(thread: Thread): Boolean


GetThreadsFromDatabase(): Thread[]


GetAllThreadsFromDatabase(): Thread[]


GetCourseInformationFromName(courseName: String): CourseInformation

- 1 to 1 with IDatabaseService


- 1 to 1 with ILogger

(U12) Sequence Diagram

SequenceDiagramU12.1.png

Actor: User

System Components: User Interface, Forum Management, Database

Step

Description

1

User Authentication: The user logs into the system.

2

Access Community Forum: The user navigates to the community forums section of the interface.

3

Initiate Thread Creation: The user clicks on the "Create New Thread" button or link.

4

Enter Thread Details: The user enters the title and description of the thread. Additional options like tagging relevant course codes or topics may be available.

5

Submit Thread: After entering all necessary information, the user submits the thread for posting.

6

Confirmation: The system displays a confirmation message indicating that the thread has been successfully created.

7

View Thread: The new thread is now visible in the forum for other users to view and respond to.

Deleting a Thread

SequenceDiagramU12.2.png

Actor: User

System Components: User Interface, Forum Management, Database

Step

Description

1

Confirm that the user is logged in (could be verified continuously through session management).

2

The user locates the thread they wish to delete. This might involve navigating through their profile to find threads they've started or directly accessing the thread through the forum.

3

The user selects the "Delete" option on the thread. This may be an icon or a link, typically located near the thread title or at the end of the first post.

4

The system prompts the user to confirm the deletion to prevent accidental removals. The user must confirm their intent to delete the thread.

5

Upon confirmation, the system deletes the thread.

6

The user receives a message confirming that the thread has been successfully deleted.

7

The thread is removed from the forum display, and the user is redirected back to the forum homepage or their profile page.

(U12) Activity Diagram

ActivityDiagarmU12.png

Step

Description

1

System displays discussion board

2

User can choose to either create or delete a thread

3

If the user chooses to create a thread, the system displays the create thread form

4

User enters a title and description for the new thread

5

User has the option to format the text and add links or images

6

User has the option to tag threads with relevant course codes or topics

7

User submits thread

8

System filters inappropriate content

9

If the input is valid, the system will display the thread

10

If the input is invalid, the system will display an error message

11

If the user chooses to delete a thread, the user will be able to select the thread to delete

12

System displays details of the chosen thread

13

User confirms deletion

14

System deletes thread from database

15

System updates discussion board

Use Case "Create, Edit, Reply, and Delete Post" (U13)

(U13) Class Diagram

ClassDiagramU13_1.png

Class

Attributes

Methods

Associations

User

UserName: String


Password: String


Email: String


IsAdmin: Boolean

None

- * to 1 with Thread


- * to 1 with Post


- 1 to 1 with UserService


- 1 to 1 with ForumPageViewModel

Student

StudentId: int

None

- 1 to 1 with User

Thread

ThreadId: int


Title: String


Creator: User


Description: String


CreationTime: DateTime


Posts: int

None

- * to 1 with User


- * to 1 with CourseInformation

Post

PostId: int


Title: String


CreationTime: DateTime


DownvoteCount: int


UpvoteCount: int


Content: String


Creator: User

None

- * to 1 with User


- * to 1 with Thread

ForumPageViewModel

ForumService: IForumService

UpvoteCommand(post: Post): Boolean


DownvoteCommand(post: Post): Boolean


ViewThreadCommand(): void


CreateThreadCommand(title: String, description: String): Boolean


DeleteThreadCommand(thread: Thread): Boolean


CreatePostCommand(thread: Thread, post: int): Boolean


EditPostCommand(thread: Thread, post: int): Boolean


ReplyPostCommand(thread: Thread, post: int): Boolean


DeletePostCommand(post: int): Boolean

- 1 to 1 with IForumService


- 1 to 1 with User

IForumPageViewModel

None

None

- 1 to 1 with ForumPageViewModel

IForumService

None

CreateThread(title: String, description: String): Boolean


GetThreadInformation(threadId: int): Thread


DeleteThread(thread: Thread): Boolean


CreatePost(thread: Thread, post: Post): Boolean


EditPost(thread: Thread, post: int): Boolean


ReplyPost(thread: Thread, post: Post): Boolean


DeletePost(post: int): Boolean

- 1 to 1 with ForumService


- 1 to 1 with ForumPageViewModel

ForumService

ImageService: IImageService


Logger: ILogger


MessageBoxService: IMessageBoxService


UploadService: IUploadService


User: User

CreateThread(title: String, description: String): Boolean


GetThreadInformation(threadId: int): Thread


DeleteThread(thread: Thread): Boolean


CreatePost(thread: Thread, post: Post): Boolean


EditPost(thread: Thread, post: int): Boolean


ReplyPost(thread: Thread, post: Post): Boolean


DeletePost(post: int): Boolean

- 1 to 1 with IForumService


- 1 to 1 with ILogger


- 1 to 1 with MessageBoxService


- 1 to 1 with IDatabaseService


- 1 to 1 with CourseInformation


- 1 to 1 with Thread


- 1 to 1 with Post

IUserService

None

Login(key: String, password: String): Boolean


Register(user: User): Boolean


Delete(): Boolean


ResetPassword(): Boolean

- 1 to 1 with UserService


- 1 to 1 with User

UserService

Logger: ILogger


MessageBoxService: IMessageBoxService


DatabaseService: IDatabaseService


User: User

Login(key: String, password: String): Boolean


Register(user: User): Boolean


Delete(): Boolean


ResetPassword(): Boolean

- 1 to 1 with IUserService


- 1 to 1 with ILogger


- 1 to 1 with MessageBoxService


- 1 to 1 with IDatabaseService

ILogger

None

None

- 1 to 1 with ForumService


- 1 to 1 with UserService

IMessageBoxService

None

ErrorMessageBox(title: String, message: String, exception: Exception, icon: Icon): void

- 1 to 1 with ForumService


- 1 to 1 with UserService

MessageBoxService

MessageBoxTitle: String


Message: String


Exception: Exception


Icon: Icon

ErrorMessageBox(title: String, message: String, exception: Exception, icon: Icon): void

- 1 to 1 with ForumService


- 1 to 1 with UserService

IUploadService

None

Upload(bytes: byte[]): Boolean

- 1 to 1 with ForumService

UploadService

ImageService: IImageService


Upload(bytes: byte[]): Boolean

None

- 1 to 1 with ForumService

IDatabaseService

None

DeleteThread(thread: Thread): Boolean


SaveCourseInformation(course: CourseInformation): Boolean


GetUsersFromDatabase(): User[]


GetUserFromKey(key: String): User


GetThreadFromId(threadId: int): Thread


SaveUser(user: User): Boolean


GetDataForAnalysis(): void


SaveThread(thread: Thread): Boolean


GetThreadsFromDatabase(): Thread[]


GetAllThreadsFromDatabase(): Thread[]


GetCourseInformationFromName(courseName: String): CourseInformation

- 1 to 1 with ForumService


- 1 to 1 with DatabaseService


- 1 to 1 with ILogger

DatabaseService

Logger: ILogger

DeleteThread(thread: Thread): Boolean


SaveCourseInformation(course: CourseInformation): Boolean


GetUsersFromDatabase(): User[]


GetUserFromKey(key: String): User


GetThreadFromId(threadId: int): Thread


SaveUser(user: User): Boolean


GetDataForAnalysis(): void


SaveThread(thread: Thread): Boolean


GetThreadsFromDatabase(): Thread[]


GetAllThreadsFromDatabase(): Thread[]


GetCourseInformationFromName(courseName: String): CourseInformation

- 1 to 1 with IDatabaseService


- 1 to 1 with ILogger

IImageService

None

Encode(stream: Stream): Bitmap

- 1 to 1 with ForumService

ImageService

Encode(stream: Stream): Bitmap

None

- 1 to 1 with ForumService

CourseInformation

Category: CourseCategory


Name: String


Description: String


Prerequisites: CourseInformation[]


Credits: int


Rating: CourseRating


IsBookmarked: Boolean


Id: int


Thread: Thread

None

- 1 to 1 with IDatabaseService


- * to 1 with Thread

Creating a Post

(U13) Sequence Diagram

SequenceDiagramU13.1.png

Actor: User

System Components: User Interface, Post Management, Database

Step

Description

1

User logs into the system and navigates to a specific thread in the community forum, where the User Interface displays the thread with existing posts and an option to add a new post.

2

User selects the option to create a new post, and the User Interface presents a form for entering the post's content.

3

User enters details for the new post and submits the form, while the User Interface captures the input data and sends it to the PostManagement component.

4

PostManagement validates the post details for inappropriate content or format errors and sends a create request to the Database.

5

Database stores the new post, assigns it an identifier, and links it to the thread, then confirms the creation back to PostManagement.

6

PostManagement receives the confirmation including a success message and details about the new post (e.g., post ID, timestamp) and notifies the User Interface of the successful creation.

7

User Interface displays the newly created post within the thread and confirms to the User, making the post live in the thread for others to view and respond to.

Editing a Post

SequenceDiagramU13.2.png

Actor: User

System Components: User Interface, Post Management, Database

Step

Description

1

User selects the edit option on their own post, and the User Interface provides an editable form pre-filled with the existing post content.

2

User modifies the content and submits the updated information, after which the User Interface sends the updated content to PostManagement.

3

PostManagement validates the updated details for format and appropriateness, and sends an update request to the Database.

4

Database updates the post details, modifies the post record, and confirms the update back to PostManagement.

5

PostManagement receives the update confirmation and sends a message indicating successful update to the User Interface.

6

User Interface updates the post display and notifies the User of the successful edit, allowing the User to see the updated content in place of the old one in the thread.

Replying to a Post

SequenceDiagramU13.3.png

Step

Description

1

User selects the reply option on a post, and the User Interface provides a form for entering the reply content.

2

User writes their reply and submits it, after which the User Interface captures the reply and forwards it to PostManagement.

3

PostManagement processes the reply, ensuring it is linked to the correct post, and sends it to the Database.

4

Database stores the reply and links it under the original post, confirming back to PostManagement.

5

PostManagement confirms the successful addition of the reply and sends a success message to the User Interface.

6

User Interface displays the new reply under the original post and confirms to the User, updating the thread to show the reply inline with the discussion.

Deleting a Post

SequenceDiagramU13.4.png

Step

Description

1

User selects the delete option on their post, and the User Interface asks the User to confirm the deletion to prevent accidental removals.

2

Upon confirmation, User Interface sends the delete request to PostManagement, including the post ID and user verification.

3

PostManagement verifies the User's authority to delete the post, checking if the User is the owner of the post or has moderator rights, and sends a delete command to the Database.

4

Database deletes the post and returns a confirmation of deletion to PostManagement.

5

PostManagement receives the deletion confirmation and notifies the User Interface.

6

User Interface updates to reflect the deletion of the post and informs the User, refreshing the forum display to show that the post is no longer available.

Last modified: 10 July 2024