From a8be44b284a0548156a4dab3ad6662fb07a172fb Mon Sep 17 00:00:00 2001
From: Alexandre Vanini <vanini.alexandre@gmail.com>
Date: Wed, 8 May 2019 11:14:04 +0200
Subject: [PATCH] [JAVA + ANGULAR]

Error handling + loading bar.
---
 client/package-lock.json                      |   8 +++
 client/package.json                           |   1 +
 client/src/app/app-routing.module.ts          |   4 +-
 client/src/app/app.component.scss             |   1 +
 client/src/app/app.module.ts                  |   8 ++-
 .../src/app/fetch-kata-show-case.service.ts   |   2 +-
 client/src/app/fetch-kata.service.ts          |   2 +-
 .../src/app/fetch-program-id.service.spec.ts  |  12 +++++
 client/src/app/fetch-program-id.service.ts    |  15 ++++++
 .../kata-displayer.component.html             |  27 +++++++---
 .../kata-displayer.component.ts               |  35 ++++++++++---
 client/src/app/kata/kata.component.html       |  15 ++++--
 client/src/app/kata/kata.component.ts         |  46 +++++++++++++-----
 client/src/app/languages_canvas.ts            |   4 +-
 .../program-create.component.html             |  17 ++++---
 .../program-create.component.scss             |   4 +-
 .../program-displayer.component.html          |  20 +++++---
 .../program-displayer.component.ts            |  10 +++-
 .../app/rnot-found/rnot-found.component.css   |   1 +
 .../app/rnot-found/rnot-found.component.html  |   2 +
 .../rnot-found/rnot-found.component.spec.ts   |  25 ++++++++++
 .../app/rnot-found/rnot-found.component.ts    |  15 ++++++
 client/src/styles.scss                        |  28 ++++++++++-
 .../server_rest/src/main/java/LiveDB.java     |  14 ++++++
 .../src/main/java/ProgramsDataBase.java       |   1 +
 .../server_rest/src/main/java/app.java        |  25 ++++++++--
 .../server_rest/target/classes/LiveDB.class   | Bin 3026 -> 3424 bytes
 .../target/classes/ProgramsDataBase.class     | Bin 682 -> 786 bytes
 .../server_rest/target/classes/app.class      | Bin 5012 -> 5777 bytes
 29 files changed, 278 insertions(+), 64 deletions(-)
 create mode 100644 client/src/app/fetch-program-id.service.spec.ts
 create mode 100644 client/src/app/fetch-program-id.service.ts
 create mode 100644 client/src/app/rnot-found/rnot-found.component.css
 create mode 100644 client/src/app/rnot-found/rnot-found.component.html
 create mode 100644 client/src/app/rnot-found/rnot-found.component.spec.ts
 create mode 100644 client/src/app/rnot-found/rnot-found.component.ts

diff --git a/client/package-lock.json b/client/package-lock.json
index 62180ff..4ac1e54 100644
--- a/client/package-lock.json
+++ b/client/package-lock.json
@@ -6473,6 +6473,14 @@
       "resolved": "https://registry.npmjs.org/ngx-bootstrap/-/ngx-bootstrap-4.1.1.tgz",
       "integrity": "sha512-2vbjMXxzFX6hz929474It6yI3LyFLm9V4vkLGlCGuhyPWi4G5kuLl3j5Wrj1CsBG9+Cz9xQM9JT6gZnkXBgaTw=="
     },
+    "ngx-ui-loader": {
+      "version": "7.2.2",
+      "resolved": "https://registry.npmjs.org/ngx-ui-loader/-/ngx-ui-loader-7.2.2.tgz",
+      "integrity": "sha512-zmwKSypGuzwyOrGpRS/p5FO5avmbCmDWcBJM11JgJyykB50/W+KbuoOm7dFP9kYMccr2JbUAkWosztNMhY3t1Q==",
+      "requires": {
+        "tslib": "^1.9.0"
+      }
+    },
     "nice-try": {
       "version": "1.0.5",
       "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
diff --git a/client/package.json b/client/package.json
index ff594db..2622bef 100644
--- a/client/package.json
+++ b/client/package.json
@@ -30,6 +30,7 @@
     "jquery": "^3.4.0",
     "ng2-ace-editor": "^0.3.9",
     "ngx-bootstrap": "^4.1.1",
+    "ngx-ui-loader": "^7.2.2",
     "rxjs": "~6.3.3",
     "tslib": "^1.9.0",
     "zone.js": "~0.8.26"
diff --git a/client/src/app/app-routing.module.ts b/client/src/app/app-routing.module.ts
index cc7a7a7..278de4a 100644
--- a/client/src/app/app-routing.module.ts
+++ b/client/src/app/app-routing.module.ts
@@ -15,8 +15,8 @@ const routes: Routes = [
   { path: '', redirectTo: '/programs', pathMatch: 'full' },
 
   {path: 'programs', component: ProgramDisplayerComponent},
-  {path: 'kata-displayer/:id/:title/:language/:sensei', component: KataDisplayerComponent},
-  {path: 'kata/:prgtitle/:sensei/:prid/:id', component: KataComponent},
+  {path: 'kata-displayer/:id', component: KataDisplayerComponent},
+  {path: 'kata/:prid/:id', component: KataComponent},
   {path: 'program_create', component: ProgramCreateComponent},
   {path: 'kata_create/:id/:language', component: KataCreateComponent},
 ];
diff --git a/client/src/app/app.component.scss b/client/src/app/app.component.scss
index fa0c94c..aa5cce1 100644
--- a/client/src/app/app.component.scss
+++ b/client/src/app/app.component.scss
@@ -1 +1,2 @@
 body{display:inline-block}
+
diff --git a/client/src/app/app.module.ts b/client/src/app/app.module.ts
index 2a35e61..2336699 100644
--- a/client/src/app/app.module.ts
+++ b/client/src/app/app.module.ts
@@ -18,6 +18,8 @@ import {KataCreateComponent} from './kata-create/kata-create.component';
 import {ProgramCreateComponent} from './program-create/program-create.component';
 import {FormsModule} from '@angular/forms';
 import {HttpClientModule} from '@angular/common/http';
+import {RNotFoundComponent} from './rnot-found/rnot-found.component';
+import {NgxUiLoaderModule} from 'ngx-ui-loader';
 
 
 @NgModule({
@@ -30,7 +32,8 @@ import {HttpClientModule} from '@angular/common/http';
     ProgramDisplayerComponent,
     KataComponent,
     KataCreateComponent,
-    ProgramCreateComponent
+    ProgramCreateComponent,
+    RNotFoundComponent
   ],
   imports: [
 
@@ -46,7 +49,8 @@ import {HttpClientModule} from '@angular/common/http';
     RouterModule,
     AceEditorModule,
     FormsModule,
-    HttpClientModule
+    HttpClientModule,
+    NgxUiLoaderModule
 
   ],
   providers: [],
diff --git a/client/src/app/fetch-kata-show-case.service.ts b/client/src/app/fetch-kata-show-case.service.ts
index e92d827..a1c5993 100644
--- a/client/src/app/fetch-kata-show-case.service.ts
+++ b/client/src/app/fetch-kata-show-case.service.ts
@@ -11,7 +11,7 @@ export class FetchKataShowCaseService {
   constructor(private http: HttpClient) {
   }
 
-  getKatasDetails(program: number) {
+  getKatasDetails(program: string) {
     return this.http.get('http://localhost:7000/program/getkatas/details/' + program + '');
   }
 }
diff --git a/client/src/app/fetch-kata.service.ts b/client/src/app/fetch-kata.service.ts
index 1ff94d5..4373e26 100644
--- a/client/src/app/fetch-kata.service.ts
+++ b/client/src/app/fetch-kata.service.ts
@@ -7,7 +7,7 @@ import {HttpClient} from '@angular/common/http';
 })
 export class FetchKataService {
 
-  getKata(programID: number, kataID: number) {
+  getKata(programID: string, kataID: string) {
     return this.http.get('http://localhost:7000/program/getkata/' + programID + '/' + kataID + '');
   }
 
diff --git a/client/src/app/fetch-program-id.service.spec.ts b/client/src/app/fetch-program-id.service.spec.ts
new file mode 100644
index 0000000..3fb956b
--- /dev/null
+++ b/client/src/app/fetch-program-id.service.spec.ts
@@ -0,0 +1,12 @@
+import { TestBed } from '@angular/core/testing';
+
+import { FetchProgramIdService } from './fetch-program-id.service';
+
+describe('FetchProgramIdService', () => {
+  beforeEach(() => TestBed.configureTestingModule({}));
+
+  it('should be created', () => {
+    const service: FetchProgramIdService = TestBed.get(FetchProgramIdService);
+    expect(service).toBeTruthy();
+  });
+});
diff --git a/client/src/app/fetch-program-id.service.ts b/client/src/app/fetch-program-id.service.ts
new file mode 100644
index 0000000..894ff34
--- /dev/null
+++ b/client/src/app/fetch-program-id.service.ts
@@ -0,0 +1,15 @@
+import {Injectable} from '@angular/core';
+import {HttpClient} from '@angular/common/http';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class FetchProgramIdService {
+
+  getDetails(id: string) {
+    return this.http.get('http://localhost:7000/program/getdetails/' + id + '');
+  }
+
+  constructor(private http: HttpClient) {
+  }
+}
diff --git a/client/src/app/kata-displayer/kata-displayer.component.html b/client/src/app/kata-displayer/kata-displayer.component.html
index 77cb659..000edee 100644
--- a/client/src/app/kata-displayer/kata-displayer.component.html
+++ b/client/src/app/kata-displayer/kata-displayer.component.html
@@ -1,11 +1,15 @@
-<div class="container" *ngIf="katas">
-  <input type="button" value="Create" routerLink="/kata_create/{{idProgram}}/{{programLanguage}}"/>
-  <span class="title">{{programTitle}}
-    <br>
+<div *ngIf="!error" class="d-flex justify-content-center" style="margin-top:2%">
+
+  <div class="container">
+    <span *ngIf="inforreceived">
+    <span class="title">{{programTitle}}
+      <br>
     <span class="subtitle">{{programSensei}} <span class="language"> {{programLanguage}}</span>
+    </span>
+      <input type="button" value="Create" routerLink="/kata_create/{{idProgram}}/{{programLanguage}}"/>
   </span>
-  </span>
-
+    </span>
+    <span *ngIf="katas">
   <div class="d-flex justify-content-start" style="margin-top:2%">
     <div class="d-flex flex-row">
       <span *ngFor="let kata of katas">
@@ -13,7 +17,7 @@
         <div class="card" style="width: 18rem;">
         <div class="card-body">
           <h5 class="card-title"><a class="title"
-                                    routerLink="/kata/{{programTitle}}/{{programSensei}}/{{idProgram}}/{{kata.id}}">{{kata.title}}</a></h5>
+                                    routerLink="/kata/{{idProgram}}/{{kata.id}}">{{kata.title}}</a></h5>
           <br/>
           <h6 class="card-subtitle mb-2 text-muted">{{kata.difficulty}} </h6>
           <span style="float: right;">{{kata.status}}</span>
@@ -26,4 +30,13 @@
       </span>
     </div>
   </div>
+  </span>
+  </div>
+
+  <span *ngIf="!katas || !inforreceived"><ngx-ui-loader></ngx-ui-loader></span>
+</div>
+
+<div *ngIf="error">
+  <app-rnot-found></app-rnot-found>
 </div>
+
diff --git a/client/src/app/kata-displayer/kata-displayer.component.ts b/client/src/app/kata-displayer/kata-displayer.component.ts
index b9375f9..dfd3115 100644
--- a/client/src/app/kata-displayer/kata-displayer.component.ts
+++ b/client/src/app/kata-displayer/kata-displayer.component.ts
@@ -1,8 +1,10 @@
 import {Component, OnInit} from '@angular/core';
 import {KataShowCase} from './kataShowCase';
-import {ActivatedRoute} from '@angular/router';
+import {ActivatedRoute, Router} from '@angular/router';
 import {Location} from '@angular/common';
 import {FetchKataShowCaseService} from '../fetch-kata-show-case.service';
+import {FetchProgramIdService} from '../fetch-program-id.service';
+import {NgxUiLoaderService} from 'ngx-ui-loader';
 
 @Component({
   selector: 'app-kata-displayer',
@@ -12,24 +14,41 @@ import {FetchKataShowCaseService} from '../fetch-kata-show-case.service';
 export class KataDisplayerComponent implements OnInit {
 
   katas: KataShowCase[];
-  idProgram: number;
+  idProgram: string;
   programTitle: string;
   programLanguage: string;
   programSensei: string;
+  error = false;
+
+  inforreceived = false;
 
   constructor(
     private route: ActivatedRoute,
     private location: Location,
-    private fetchKataShowCaseService: FetchKataShowCaseService
+    private fetchKataShowCaseService: FetchKataShowCaseService,
+    private fetchProgramDetailsService: FetchProgramIdService,
+    private ngxLoader: NgxUiLoaderService
   ) {
   }
 
   getKatas(): void {
-    this.idProgram = +this.route.snapshot.paramMap.get('id');
-    this.programSensei = this.route.snapshot.paramMap.get('sensei');
-    this.programLanguage = this.route.snapshot.paramMap.get('language');
-    this.programTitle = this.route.snapshot.paramMap.get('title');
-    this.fetchKataShowCaseService.getKatasDetails(this.idProgram).subscribe((data: KataShowCase[]) => this.katas = data);
+    this.idProgram = this.route.snapshot.paramMap.get('id');
+    this.ngxLoader.start();
+    this.fetchProgramDetailsService.getDetails(this.idProgram).subscribe((data: string[]) => {
+      this.programTitle = data[0];
+      this.programLanguage = data[1];
+      this.programSensei = data[2];
+      this.inforreceived = true;
+      this.fetchKataShowCaseService.getKatasDetails(this.idProgram).subscribe((datas: KataShowCase[]) => {
+        this.katas = datas;
+        this.ngxLoader.stop();
+      });
+    }, (error1 => {
+      if (error1.status === 404) {
+        this.error = true;
+        this.ngxLoader.stop();
+      }
+    }));
   }
 
   ngOnInit() {
diff --git a/client/src/app/kata/kata.component.html b/client/src/app/kata/kata.component.html
index cc8b5b7..26f4e52 100644
--- a/client/src/app/kata/kata.component.html
+++ b/client/src/app/kata/kata.component.html
@@ -1,13 +1,15 @@
-<div *ngIf="kata" class="d-flex justify-content-center" style="margin-top:2%">
+<div *ngIf="!error" class="d-flex justify-content-center" style="margin-top:2%">
+  <span *ngIf="katareceived">
   <div class="d-flex flex-column">
-    <div class="p-2 title">{{kata.title}} <a routerLink="/kata-displayer/{{programID}}/{{kata.title}}/{{kata.language}}/{{programSensei}}">- {{programTitle}}</a>
+    <div class="p-2 title">{{kata.title}} <a routerLink="/kata-displayer/{{programID}}">- {{programTitle}}</a>
       <br><span class="subtitle">{{programSensei}} <span class="language"> {{kata.language}}</span></span></div>
 
 
     <div class="p-2 "><label class="header">rules :</label></div>
     <div class="p-2 ">
       <textarea disabled style="text-align: justify">{{kata.rules}}</textarea>
-      <app-terminal-code style="margin-left: 20px;" [code]="kata.canva" [type]="kata.language" (new)="OnNewEvent($event)"></app-terminal-code>
+      <app-terminal-code style="margin-left: 20px;" [code]="kata.canva" [type]="kata.language"
+                         (new)="OnNewEvent($event)"></app-terminal-code>
     </div>
 
     <div class="p-2">
@@ -19,11 +21,16 @@
     <div class="p-2">
 
       <button (click)="compile(kata.language,kata.canva,kata.cassert)" class="code">TRY MY SOLUTION</button>
-      <button  style="margin-right: 10px" class="code">SURRENDER</button>
+      <button style="margin-right: 10px" class="code">SURRENDER</button>
     </div>
   </div>
+    </span>
+  <span *ngIf="!katareceived"><ngx-ui-loader></ngx-ui-loader></span>
+</div>
 
 
+<div *ngIf="error">
+  <app-rnot-found></app-rnot-found>
 </div>
 
 
diff --git a/client/src/app/kata/kata.component.ts b/client/src/app/kata/kata.component.ts
index 766ee5b..0c2d97e 100644
--- a/client/src/app/kata/kata.component.ts
+++ b/client/src/app/kata/kata.component.ts
@@ -1,10 +1,11 @@
 import {Component, OnInit} from '@angular/core';
-import {ActivatedRoute} from '@angular/router';
+import {ActivatedRoute, Router} from '@angular/router';
 import {Location} from '@angular/common';
 import {FetchKataService} from '../fetch-kata.service';
 import {Kata} from './kata';
-import * as $ from 'jquery';
 import {CompilationService} from '../compilation.service';
+import {FetchProgramIdService} from '../fetch-program-id.service';
+import {NgxUiLoaderService} from 'ngx-ui-loader';
 
 @Component({
   selector: 'app-kata',
@@ -14,31 +15,50 @@ import {CompilationService} from '../compilation.service';
 export class KataComponent implements OnInit {
 
   kata: Kata;
-  idKata: number;
+  idKata: string;
   status = 2;
   result = '';
-  programID: number;
-
+  programID: string;
   programTitle: string;
   programSensei: string;
+  error = false;
+
+  katareceived = false;
 
   constructor(
     private route: ActivatedRoute,
     private location: Location,
     private fetchKataService: FetchKataService,
-    private compilationService: CompilationService
+    private compilationService: CompilationService,
+    private fetchProgramDetailsService: FetchProgramIdService,
+    private ngxLoader: NgxUiLoaderService
   ) {
   }
 
   getKata(): void {
-    this.idKata = +this.route.snapshot.paramMap.get('id');
-    this.programID = +this.route.snapshot.paramMap.get('prid');
-    this.programSensei = this.route.snapshot.paramMap.get('sensei');
-    this.programTitle = this.route.snapshot.paramMap.get('prgtitle');
-    this.fetchKataService.getKata(this.programID, this.idKata).subscribe((data: Kata) => {
-      this.kata = data;
+    this.ngxLoader.start();
+    this.programID = this.route.snapshot.paramMap.get('prid');
+    this.fetchProgramDetailsService.getDetails(this.programID).subscribe((data: string[]) => {
+      this.idKata = this.route.snapshot.paramMap.get('id');
+      this.programSensei = data[2];
+      this.programTitle = data[0];
+      this.fetchKataService.getKata(this.programID, this.idKata).subscribe((datas: Kata) => {
+          this.kata = datas;
+          this.ngxLoader.stop();
+          this.katareceived = true;
+        },
+        (error1 => {
+          if (error1.status === 404) {
+            this.ngxLoader.stop();
+            this.error = true;
+          }
+        }));
+    }, error1 => {
+      if (error1.status === 404) {
+        this.ngxLoader.stop();
+        this.error = true;
+      }
     });
-
   }
 
   OnNewEvent(event: any): void {
diff --git a/client/src/app/languages_canvas.ts b/client/src/app/languages_canvas.ts
index 059d8a0..feb2c78 100644
--- a/client/src/app/languages_canvas.ts
+++ b/client/src/app/languages_canvas.ts
@@ -9,7 +9,7 @@ export class Canva {
 export const LANG: Canva[] = [
   {
     id: 'python', assertCanva: 'from assertpy import assert_that\nimport sample as m' + '\n\n' +
-      '# Example : assert_that(m.yourfunction(someValues)).is_equal_to(targetedValues)', codeCanva: '# Write your code here'
+      '# Example : \n# assert_that(m.yourfunction(someValues)).is_equal_to(targetedValues)', codeCanva: '# Write your code here'
   },
   {
     id: 'java', assertCanva: 'import static org.junit.Assert.*;\n' +
@@ -17,7 +17,7 @@ export const LANG: Canva[] = [
       'public class Main {\n' +
       '\n' +
       '    public static void main(String[] args) {\n' +
-      '       // Example : assertEquals(Kata.yourfunction(someValues,targetedValues))' +
+      '       // Example : \n// assertEquals(Kata.yourfunction(someValues,targetedValues))' +
       '    }\n' +
       '}', codeCanva: 'public class Kata {\n' +
       '\n' +
diff --git a/client/src/app/program-create/program-create.component.html b/client/src/app/program-create/program-create.component.html
index f8b250a..965078a 100644
--- a/client/src/app/program-create/program-create.component.html
+++ b/client/src/app/program-create/program-create.component.html
@@ -8,15 +8,16 @@
     <div class="p-2"><label>Tags</label><input type="text" [(ngModel)]="programTags" placeholder=" arrays,writeable,.."/></div>
     <div class="p-2">
 
-        <input type="button" (click)="createProgram(false)" value="CREATE"/>
-        <input type="button" (click)="createProgram(true)" style="float:right" value="CREATE + NEW KATA"/>
+        <input type="button" (click)="createProgram(false)" class="button" value="CREATE"/>
+        <input type="button" (click)="createProgram(true)" class="button" style="float:right" value="CREATE + NEW KATA"/>
+
     </div>
+
+      <div class="p-2">
+        <input type="button" class="button" style="float:right" value="addad + NEW KATA"/>
+      </div>
     </fieldset>
   </div>
 </div>
-<!-- Material input -->
-<div class="md-form">
-  <i class="fas fa-envelope prefix"></i>
-  <input type="text" id="inputIconEx1" class="form-control">
-  <label for="inputIconEx1">E-mail address</label>
-</div>
+
+
diff --git a/client/src/app/program-create/program-create.component.scss b/client/src/app/program-create/program-create.component.scss
index cf83ab1..3ca9d28 100644
--- a/client/src/app/program-create/program-create.component.scss
+++ b/client/src/app/program-create/program-create.component.scss
@@ -25,7 +25,7 @@ select {
 label{
   margin-top:.4em;
 }
-
+/*
 input[type=button]{
 
   background-color: rgba(63, 67, 77, 1);
@@ -36,7 +36,7 @@ input[type=button]{
 
 }:focus{
   outline:none;
- }
+ }*/
 
 textarea{
   padding: .6em 1.4em .5em .8em;
diff --git a/client/src/app/program-displayer/program-displayer.component.html b/client/src/app/program-displayer/program-displayer.component.html
index 538a48e..c71dce0 100644
--- a/client/src/app/program-displayer/program-displayer.component.html
+++ b/client/src/app/program-displayer/program-displayer.component.html
@@ -1,13 +1,11 @@
-<div class="d-flex justify-content-center"  *ngIf="programs" style="margin-top:2%">
-  <div class="d-flex flex-column">
-    <div class="p-2" style="width:200px"></div>
-    <div class="p-2"><h1>Tous les programmes disponibles : </h1></div>
-
-    <div class="p-2" >
-  <span  *ngFor="let program of programs">
+<div class="d-flex justify-content-center" style="margin-top:2%">
+  <div *ngIf="programs" class="d-flex flex-column">
+    <div class="p-2"><h1>All available programs</h1></div>
+    <div class="p-2">
+  <span *ngFor="let program of programs">
       <div class="card" style="width: 18rem;">
         <div class="card-body">
-          <a routerLink="/kata-displayer/{{program.programID}}/{{program.title}}/{{program.language}}/{{program.sensei}}">
+          <a routerLink="/kata-displayer/{{program.programID}}">
             <h5 class="card-title">{{program.title}}</h5></a>
           <h6 class="card-subtitle mb-2 text-muted"><a class="sensei" href="">{{program.sensei}} </a>
             <a href=""><span class="language">{{program.language}}</span></a></h6>
@@ -22,4 +20,10 @@
   </span>
     </div>
   </div>
+  <div class="d-flex flex-column" *ngIf="programReceivedFailed">
+    <div class="p-2">
+      <h1>Oops.. no program available ..</h1>
+    </div>
+    <h2><a routerLink="/program_create">Create a new program</a></h2>
+  </div>
 </div>
diff --git a/client/src/app/program-displayer/program-displayer.component.ts b/client/src/app/program-displayer/program-displayer.component.ts
index 54c239a..fff044f 100644
--- a/client/src/app/program-displayer/program-displayer.component.ts
+++ b/client/src/app/program-displayer/program-displayer.component.ts
@@ -11,12 +11,20 @@ export class ProgramDisplayerComponent implements OnInit {
 
 
   programs: Program[];
+  programReceivedFailed = false;
 
   constructor(private fetchProgramService: FetchProgramService) {
   }
 
   getProgram(): void {
-    this.fetchProgramService.getPrograms().subscribe((data: Program[]) => this.programs = data);
+    this.fetchProgramService.getPrograms().subscribe((data: Program[]) => {
+      this.programs = data;
+
+    }, error1 => {
+      if (error1.status === 404) {
+        this.programReceivedFailed = true;
+      }
+    });
   }
 
   ngOnInit() {
diff --git a/client/src/app/rnot-found/rnot-found.component.css b/client/src/app/rnot-found/rnot-found.component.css
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/client/src/app/rnot-found/rnot-found.component.css
@@ -0,0 +1 @@
+
diff --git a/client/src/app/rnot-found/rnot-found.component.html b/client/src/app/rnot-found/rnot-found.component.html
new file mode 100644
index 0000000..c28773e
--- /dev/null
+++ b/client/src/app/rnot-found/rnot-found.component.html
@@ -0,0 +1,2 @@
+<span class="NOTFOUND">SERVER ERROR: 404 NOT FOUND</span>
+
diff --git a/client/src/app/rnot-found/rnot-found.component.spec.ts b/client/src/app/rnot-found/rnot-found.component.spec.ts
new file mode 100644
index 0000000..9b1d280
--- /dev/null
+++ b/client/src/app/rnot-found/rnot-found.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { RNotFoundComponent } from './rnot-found.component';
+
+describe('RNotFoundComponent', () => {
+  let component: RNotFoundComponent;
+  let fixture: ComponentFixture<RNotFoundComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ RNotFoundComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(RNotFoundComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/client/src/app/rnot-found/rnot-found.component.ts b/client/src/app/rnot-found/rnot-found.component.ts
new file mode 100644
index 0000000..c25c95f
--- /dev/null
+++ b/client/src/app/rnot-found/rnot-found.component.ts
@@ -0,0 +1,15 @@
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+  selector: 'app-rnot-found',
+  templateUrl: './rnot-found.component.html',
+  styleUrls: ['./rnot-found.component.css']
+})
+export class RNotFoundComponent implements OnInit {
+
+  constructor() { }
+
+  ngOnInit() {
+  }
+
+}
diff --git a/client/src/styles.scss b/client/src/styles.scss
index 7e7239a..126847d 100644
--- a/client/src/styles.scss
+++ b/client/src/styles.scss
@@ -1,4 +1,28 @@
 /* You can add global styles to this file, and also import other style files */
 
-html, body { height: 100%; }
-body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
+html, body {
+  height: 100%;
+  --color-cloud: rgba(236, 240, 241, 1);
+  --color-dark-blue: rgba(43, 47, 57, 1);
+  --color-light-blue: rgba(63, 67, 77, 1);
+}
+
+body {
+  margin: 0;
+  font-family: Roboto, "Helvetica Neue", sans-serif;
+}
+
+.NOTFOUND {
+  color: rgba(83, 87, 97, 1);
+  font-size: 50px;
+}
+
+.button {
+  background-color: var(--color-light-blue) ;
+  border: 0;
+  padding: .4em .7em .4em .7em;
+  border-radius: .4em;
+  color: var(--color-cloud);
+  border:3px solid var(--color-cloud);
+
+}
diff --git a/tests/serveur_compilation/server_rest/src/main/java/LiveDB.java b/tests/serveur_compilation/server_rest/src/main/java/LiveDB.java
index 334fe38..2d8063c 100644
--- a/tests/serveur_compilation/server_rest/src/main/java/LiveDB.java
+++ b/tests/serveur_compilation/server_rest/src/main/java/LiveDB.java
@@ -60,4 +60,18 @@ public class LiveDB extends ProgramsDataBase {
         return ktsc;
     }
 
+    public ArrayList<String> getProgramDetailsByID(String id){
+        ArrayList<String> infos = new ArrayList<>();
+
+        for (Program p : this.programs)
+            if(p.getId().equals(id)){
+                infos.add(p.getTitle());
+                infos.add(p.getLanguage());
+                infos.add(p.getSensei());
+                break;
+            }
+
+        return infos;
+    }
+
 }
\ No newline at end of file
diff --git a/tests/serveur_compilation/server_rest/src/main/java/ProgramsDataBase.java b/tests/serveur_compilation/server_rest/src/main/java/ProgramsDataBase.java
index fdd800a..f0ece14 100644
--- a/tests/serveur_compilation/server_rest/src/main/java/ProgramsDataBase.java
+++ b/tests/serveur_compilation/server_rest/src/main/java/ProgramsDataBase.java
@@ -6,4 +6,5 @@ public abstract class ProgramsDataBase {
     public abstract ArrayList<ProgramShowCase> getProgramsDetails();
     public abstract Kata getProgramKata(String programID, String kataID);
     public abstract ArrayList<KataShowCase> getProgramKatasDetails(String programID);
+    public abstract ArrayList<String> getProgramDetailsByID(String id);
 }
diff --git a/tests/serveur_compilation/server_rest/src/main/java/app.java b/tests/serveur_compilation/server_rest/src/main/java/app.java
index 7e406b8..a30622d 100644
--- a/tests/serveur_compilation/server_rest/src/main/java/app.java
+++ b/tests/serveur_compilation/server_rest/src/main/java/app.java
@@ -5,6 +5,7 @@ import java.io.*;
 import java.net.ConnectException;
 import java.net.HttpURLConnection;
 import java.net.URL;
+import java.util.ArrayList;
 
 public class app {
 
@@ -66,15 +67,33 @@ public class app {
         });
 
         app.get("/program/getdetails", ctx -> {
-            ctx.json(db.getProgramsDetails());
+            ArrayList<ProgramShowCase> prgsc = db.getProgramsDetails();
+            if (prgsc.size() == 0)
+                ctx.status(404);
+            else
+                ctx.json(prgsc);
         });
 
         app.get("/program/getkatas/details/:id", ctx -> {
-            ctx.json(db.getProgramKatasDetails(ctx.pathParam("id")));
+            ArrayList<KataShowCase> ktsc = db.getProgramKatasDetails(ctx.pathParam("id"));
+            ctx.json(ktsc);
         });
 
         app.get("/program/getkata/:prid/:id", ctx -> {
-            ctx.json(db.getProgramKata(ctx.pathParam("prid"),ctx.pathParam("id")));
+
+            Kata kata = db.getProgramKata(ctx.pathParam("prid"), ctx.pathParam("id"));
+            if (kata.getId() == null)
+                ctx.status(404);
+            else
+                ctx.json(kata);
+        });
+
+        app.get("program/getdetails/:id", ctx -> {
+            ArrayList<String> s = db.getProgramDetailsByID(ctx.pathParam("id"));
+            if (s.size() == 0)
+                ctx.status(404);
+            else
+                ctx.json(s);
         });
 
     }
diff --git a/tests/serveur_compilation/server_rest/target/classes/LiveDB.class b/tests/serveur_compilation/server_rest/target/classes/LiveDB.class
index e7abcb7ca81754ed034a5c3e5f1f504b1f140e3f..ab6ebb636dbde39b1bc15d10352aff1beab6f9e2 100644
GIT binary patch
delta 676
zcmca4{y?h!)W2Q(7#J8#7<#!F6d8iq8A7-im>7aN859^oK|~mc8xA5OxEU-NB0)qH
zJ3}-V0~bRK7lQ;tEEhu@Lp+F^03s4WL=rngGKfwA5vd>|4Me1ahzu?UL556rhAfcg
zU<D8v!_JTmqEkRb4hKUn7lSlI9y>!mJ43<7`Id}~g`00Oo@G=OO;0TeD9TSSO3Zah
zElJGGDR!##bYWy*%1mKoV9m@+%P(eRm>j?)E}oTGmZ+bTn3t{}TvC*omu_um&B$P@
zF?j)#$m9lQQ2})M$qSiXt&13nc^FC<N_iN{7|MAVDi|sm8Q7ur@i0^|RP!*@FjTWM
z)bcRYft1!WH1IGqGBoipG*4D!5p!+<sb~ceZ6Kl@M07B8@-S#HbTKlpcqf)5GBWUh
zsNjtJa_7Y2R33(IhH6FzmJojze~_}C%~dP~OpNTCU$Z@8sdr~!V$fn>V0g~J#K6kH
zz!0{Zfhlr31GBHz76z7W4D5coI~h0_8D=ur>F#9UWMnwNz-7fE$+C@sTYDP=?@R_2
z9S}!o8v|Q7m?Z*d34>V68Q7Np-><WQfq{XAL7RbrL5+cvfq}t+frG(`L50D&p22{@
zg~5u!mBEF<jlqw>ogt9HnIVM1i$RBhfkBIbg+YZum%)_5h=B#<I0jt?Jq8d6WAJ5g
zW?*FCVDMw`V^C&bVz6OgVBmp^_%kpuSTHa!2r@ALWe{LzU}9&m{LSF-i-Czjg@J*A
Qi6MZ2ks%P|C?<v=0ObUKuK)l5

delta 348
zcmaDLbxFMb)W2Q(7#J8#7&^EZ6dC;38T`2zm>B#x859@-Ktv#j8w4VPxfv`OLO?_)
zJ3|;30~bR$7lQ;t1Q$ajLllS`4I*MdL@YZ)9Egqw5eXn75kw?`h-5AXL537|hE$Md
zKLrpO&d!hqqT@kCItN1r7lSlICObnGJ45!y`Id}~Ih$`Xo@JbD&f-v?%aF&zkk3%S
z!%)aj#KTa`P{PQ-9#E8@UX+;2!%)gl#=}s~P{z(s!NX7qQd-4O&BIW`P|L$m$6(FK
zzz<a#oRMGdoLHR7!%z>>(f}eFK|~XXXl7{PVbEY`Wn^ISPAo}eWZ(f&AU&cGO>GQi
hj0`Lx{x1F?b?uwESqqpL**4d(KVo5JU|?eK1ppI+K@k7|

diff --git a/tests/serveur_compilation/server_rest/target/classes/ProgramsDataBase.class b/tests/serveur_compilation/server_rest/target/classes/ProgramsDataBase.class
index bcfdd67e6dde0c9b6d912f6e36b8665e556f522d..4f73f058ad7f7eb5a64a9773bbba0c50cc4f7ed6 100644
GIT binary patch
delta 116
zcmZ3*I*Cp6)W2Q(7#J8#805Jam>Fc)8D!ZR<Ti@#VU!e2Pb~>3%1<v!%ymgENzBYC
zcB=GrVPvqKoW-aiWaE>SSeB@tlbDyTA6!zDnU_BK3}YN4`($mVQYjWj1_=f+21W)!
R1_lNu21y1+1}QL08UQwx8vOtO

delta 51
zcmbQlwu)8s)W2Q(7#J8#7-YE^m>Hzl8Kl`6WHyTKVVtbV6v@aoxtXbyi-D0rf`Ng7
Hi9r$oK28b7

diff --git a/tests/serveur_compilation/server_rest/target/classes/app.class b/tests/serveur_compilation/server_rest/target/classes/app.class
index b6aa526cb48f6549b6af307f8969b230ef95c720..1c9802a0ba2547a05908d5756ebce45a16bfac3e 100644
GIT binary patch
delta 3157
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
BS+xKF

delta 2412
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
Ra8?(b)dOes!&ws<ngJOPxA6b~

-- 
GitLab