9003. Online Judge - Frontend with AngularAngular
Setup frontend UI for Online Judge app with Angular.
1. Project Structure
1.1 Client Files
All source files for client is under ‘./src’ folder.
1.2 Angular Project
This app is created by ‘ng new’ command with Angular CLI.
2. Main Components
Separate app functions to different components as follows.
| Component | Path | Description |
|---|---|---|
| component | ’./src/app/component’ | UI components |
| interceptor | ’./src/app/interceptor’ | HTTP interceptor |
| model | ’./src/app/models’ | Model class |
| service | ’./src/app/services’ | HTTP services to communicate with backend RESTful services |
| util | ’./src/app/util’ | Helper class |
2.1 UI Components
The app page contains 5 components. In ‘./src/app/components/pages/app.component.html’, setup the app page as follows.
<div class="mainpage">
<app-widget-progress-bar></app-widget-progress-bar>
<app-header></app-header>
<app-alert></app-alert>
<router-outlet></router-outlet>
<app-footer></app-footer>
</div>
Details are explained in the table.
| selector | Description |
|---|---|
| app-widget-progress-bar | Progress bar displays whenever Http request happens |
| app-header | Top menus |
| app-alert | Common alert dialog, eg. Save, Submit |
| router-outlet | Angular Routing, navigate to sub component |
| app-footer | Footage of the app |
2.2 Http Interceptor
Use HttpInterceptor to intercept and modify HTTP requests globally.
| File Name | Class Name | Description |
|---|---|---|
| cookie.interceptor.ts | CookieHttpInterceptor | Manipulate Cookies settings on request |
| error.interceptor.ts | ErrorHttpInterceptor | Handle http request error globally |
| jwt.interceptor.ts | JwtHttpInterceptor | Add token to each http request |
| timeout.interceptor.ts | TimeoutHttpInterceptor | Set timeout before sending http request |
2.3 Model
Model class for user, question, submission, etc.
2.4 Service
Services are collections of common methods. Most of the services are used to send HTTP requests to call RESTful API.
| File Name | Class Name | Description |
|---|---|---|
| alert.service.ts | AlertService | Display Alert message from anywhere. The Alert will be shown at the top of the page. |
| auth-guard.service.ts | AuthGuardService | Guard access right. If user hasn’t logged in, he/she will be navigated to login page if he/she tries to access some pages only available for registered users. |
| authentication.service.ts | AuthenticationService | Http requests for register, login, etc. |
| database.service.ts | DatabaseService | Http requests for data import and export. |
| question.service.ts | QuestionService | Http requests for question management. |
| submission.service.ts | SubmissionService | Http requests for solution submission. |
| user.service.ts | UserService | Http requests for user management. |
2.5 Util
Some helper methods, string manipulation, cookie manipulation, etc.
3. Angular Routing
Define all the routings in file ‘src/app/app.route.ts’. Notice, some components are guarded by ‘AuthGuardService’. These components are accessible only when user has logged in.
import { RouterModule, Routes } from "@angular/router";
// components
import {
AlertComponent,
AppComponent,
HeaderComponent,
FooterComponent,
HomepageComponent,
SignupComponent,
LoginComponent,
ResetpwdComponent,
ProfileComponent,
DatabaseComponent,
QuestionsComponent,
QuestionComponent,
EditorComponent,
UsersComponent,
UserComponent,
WysiwygComponent,
AlgorithmQuestionComponent,
AlgorithmQuestionsComponent,
SubmissionComponent
} from "./components/";
// services
import { AuthGuardService } from "./services/";
export const appRoutes: Routes = [
{ path: "", component: HomepageComponent },
{ path: "homepage", component: HomepageComponent },
{ path: "questions", component: AlgorithmQuestionsComponent },
{ path: "question/:uniquename", component: AlgorithmQuestionComponent },
{ path: "submission/:id", component: SubmissionComponent },
{
path: "admin/database",
component: DatabaseComponent,
canActivate: [AuthGuardService]
},
{
path: "admin/users",
component: UsersComponent,
canActivate: [AuthGuardService]
},
{
path: "admin/user",
component: UserComponent,
canActivate: [AuthGuardService]
},
{
path: "admin/user/:_id",
component: UserComponent,
canActivate: [AuthGuardService]
},
{
path: "admin/questions",
component: QuestionsComponent,
canActivate: [AuthGuardService]
},
{
path: "admin/question",
component: QuestionComponent,
canActivate: [AuthGuardService]
},
{
path: "admin/question/:_id",
component: QuestionComponent,
canActivate: [AuthGuardService]
},
{
path: "editor",
component: EditorComponent
},
{
path: "wysiwyg",
component: WysiwygComponent
},
{ path: "signup", component: SignupComponent },
{ path: "login", component: LoginComponent },
{
path: "resetpwd",
component: ResetpwdComponent,
canActivate: [AuthGuardService]
},
{
path: "profile",
component: ProfileComponent,
canActivate: [AuthGuardService]
},
// otherwise redirect to home
{ path: "**", redirectTo: "" }
];