modif
This commit is contained in:
commit
d270f2f1f5
59 changed files with 16099 additions and 0 deletions
17
.editorconfig
Normal file
17
.editorconfig
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
# Editor configuration, see https://editorconfig.org
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.ts]
|
||||||
|
quote_type = single
|
||||||
|
ij_typescript_use_double_quotes = false
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
max_line_length = off
|
||||||
|
trim_trailing_whitespace = false
|
||||||
42
.gitignore
vendored
Normal file
42
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
# See https://docs.github.com/get-started/getting-started-with-git/ignoring-files for more about ignoring files.
|
||||||
|
|
||||||
|
# Compiled output
|
||||||
|
/dist
|
||||||
|
/tmp
|
||||||
|
/out-tsc
|
||||||
|
/bazel-out
|
||||||
|
|
||||||
|
# Node
|
||||||
|
/node_modules
|
||||||
|
npm-debug.log
|
||||||
|
yarn-error.log
|
||||||
|
|
||||||
|
# IDEs and editors
|
||||||
|
.idea/
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
.c9/
|
||||||
|
*.launch
|
||||||
|
.settings/
|
||||||
|
*.sublime-workspace
|
||||||
|
|
||||||
|
# Visual Studio Code
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.history/*
|
||||||
|
|
||||||
|
# Miscellaneous
|
||||||
|
/.angular/cache
|
||||||
|
.sass-cache/
|
||||||
|
/connect.lock
|
||||||
|
/coverage
|
||||||
|
/libpeerconnection.log
|
||||||
|
testem.log
|
||||||
|
/typings
|
||||||
|
|
||||||
|
# System files
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
4
.vscode/extensions.json
vendored
Normal file
4
.vscode/extensions.json
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846
|
||||||
|
"recommendations": ["angular.ng-template"]
|
||||||
|
}
|
||||||
20
.vscode/launch.json
vendored
Normal file
20
.vscode/launch.json
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "ng serve",
|
||||||
|
"type": "chrome",
|
||||||
|
"request": "launch",
|
||||||
|
"preLaunchTask": "npm: start",
|
||||||
|
"url": "http://localhost:4200/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ng test",
|
||||||
|
"type": "chrome",
|
||||||
|
"request": "launch",
|
||||||
|
"preLaunchTask": "npm: test",
|
||||||
|
"url": "http://localhost:9876/debug.html"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
42
.vscode/tasks.json
vendored
Normal file
42
.vscode/tasks.json
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
{
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"type": "npm",
|
||||||
|
"script": "start",
|
||||||
|
"isBackground": true,
|
||||||
|
"problemMatcher": {
|
||||||
|
"owner": "typescript",
|
||||||
|
"pattern": "$tsc",
|
||||||
|
"background": {
|
||||||
|
"activeOnStart": true,
|
||||||
|
"beginsPattern": {
|
||||||
|
"regexp": "(.*?)"
|
||||||
|
},
|
||||||
|
"endsPattern": {
|
||||||
|
"regexp": "bundle generation complete"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "npm",
|
||||||
|
"script": "test",
|
||||||
|
"isBackground": true,
|
||||||
|
"problemMatcher": {
|
||||||
|
"owner": "typescript",
|
||||||
|
"pattern": "$tsc",
|
||||||
|
"background": {
|
||||||
|
"activeOnStart": true,
|
||||||
|
"beginsPattern": {
|
||||||
|
"regexp": "(.*?)"
|
||||||
|
},
|
||||||
|
"endsPattern": {
|
||||||
|
"regexp": "bundle generation complete"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
59
README.md
Normal file
59
README.md
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
# Project
|
||||||
|
|
||||||
|
This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 19.2.0.
|
||||||
|
|
||||||
|
## Development server
|
||||||
|
|
||||||
|
To start a local development server, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ng serve
|
||||||
|
```
|
||||||
|
|
||||||
|
Once the server is running, open your browser and navigate to `http://localhost:4200/`. The application will automatically reload whenever you modify any of the source files.
|
||||||
|
|
||||||
|
## Code scaffolding
|
||||||
|
|
||||||
|
Angular CLI includes powerful code scaffolding tools. To generate a new component, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ng generate component component-name
|
||||||
|
```
|
||||||
|
|
||||||
|
For a complete list of available schematics (such as `components`, `directives`, or `pipes`), run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ng generate --help
|
||||||
|
```
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
To build the project run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ng build
|
||||||
|
```
|
||||||
|
|
||||||
|
This will compile your project and store the build artifacts in the `dist/` directory. By default, the production build optimizes your application for performance and speed.
|
||||||
|
|
||||||
|
## Running unit tests
|
||||||
|
|
||||||
|
To execute unit tests with the [Karma](https://karma-runner.github.io) test runner, use the following command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ng test
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running end-to-end tests
|
||||||
|
|
||||||
|
For end-to-end (e2e) testing, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ng e2e
|
||||||
|
```
|
||||||
|
|
||||||
|
Angular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs.
|
||||||
|
|
||||||
|
## Additional Resources
|
||||||
|
|
||||||
|
For more information on using the Angular CLI, including detailed command references, visit the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page.
|
||||||
108
angular.json
Normal file
108
angular.json
Normal file
|
|
@ -0,0 +1,108 @@
|
||||||
|
{
|
||||||
|
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||||
|
"version": 1,
|
||||||
|
"newProjectRoot": "projects",
|
||||||
|
"projects": {
|
||||||
|
"project": {
|
||||||
|
"projectType": "application",
|
||||||
|
"schematics": {
|
||||||
|
"@schematics/angular:component": {
|
||||||
|
"standalone": false
|
||||||
|
},
|
||||||
|
"@schematics/angular:directive": {
|
||||||
|
"standalone": false
|
||||||
|
},
|
||||||
|
"@schematics/angular:pipe": {
|
||||||
|
"standalone": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "",
|
||||||
|
"sourceRoot": "src",
|
||||||
|
"prefix": "app",
|
||||||
|
"architect": {
|
||||||
|
"build": {
|
||||||
|
"builder": "@angular-devkit/build-angular:application",
|
||||||
|
"options": {
|
||||||
|
"outputPath": "dist/project",
|
||||||
|
"index": "src/index.html",
|
||||||
|
"browser": "src/main.ts",
|
||||||
|
"polyfills": [
|
||||||
|
"zone.js"
|
||||||
|
],
|
||||||
|
"tsConfig": "tsconfig.app.json",
|
||||||
|
"assets": [
|
||||||
|
{
|
||||||
|
"glob": "**/*",
|
||||||
|
"input": "public"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"styles": [
|
||||||
|
"@angular/material/prebuilt-themes/cyan-orange.css",
|
||||||
|
"src/styles.css"
|
||||||
|
],
|
||||||
|
"scripts": []
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"production": {
|
||||||
|
"budgets": [
|
||||||
|
{
|
||||||
|
"type": "initial",
|
||||||
|
"maximumWarning": "500kB",
|
||||||
|
"maximumError": "1MB"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "anyComponentStyle",
|
||||||
|
"maximumWarning": "4kB",
|
||||||
|
"maximumError": "8kB"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputHashing": "all"
|
||||||
|
},
|
||||||
|
"development": {
|
||||||
|
"optimization": false,
|
||||||
|
"extractLicenses": false,
|
||||||
|
"sourceMap": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultConfiguration": "production"
|
||||||
|
},
|
||||||
|
"serve": {
|
||||||
|
"builder": "@angular-devkit/build-angular:dev-server",
|
||||||
|
"configurations": {
|
||||||
|
"production": {
|
||||||
|
"buildTarget": "project:build:production"
|
||||||
|
},
|
||||||
|
"development": {
|
||||||
|
"buildTarget": "project:build:development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultConfiguration": "development"
|
||||||
|
},
|
||||||
|
"extract-i18n": {
|
||||||
|
"builder": "@angular-devkit/build-angular:extract-i18n"
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"builder": "@angular-devkit/build-angular:karma",
|
||||||
|
"options": {
|
||||||
|
"polyfills": [
|
||||||
|
"zone.js",
|
||||||
|
"zone.js/testing"
|
||||||
|
],
|
||||||
|
"tsConfig": "tsconfig.spec.json",
|
||||||
|
"assets": [
|
||||||
|
{
|
||||||
|
"glob": "**/*",
|
||||||
|
"input": "public"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"styles": [
|
||||||
|
"@angular/material/prebuilt-themes/cyan-orange.css",
|
||||||
|
"src/styles.css"
|
||||||
|
],
|
||||||
|
"scripts": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
14881
package-lock.json
generated
Normal file
14881
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
39
package.json
Normal file
39
package.json
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
{
|
||||||
|
"name": "project",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"scripts": {
|
||||||
|
"ng": "ng",
|
||||||
|
"start": "ng serve",
|
||||||
|
"build": "ng build",
|
||||||
|
"watch": "ng build --watch --configuration development",
|
||||||
|
"test": "ng test"
|
||||||
|
},
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@angular/cdk": "^19.2.19",
|
||||||
|
"@angular/common": "^19.2.0",
|
||||||
|
"@angular/compiler": "^19.2.0",
|
||||||
|
"@angular/core": "^19.2.0",
|
||||||
|
"@angular/forms": "^19.2.0",
|
||||||
|
"@angular/material": "^19.2.19",
|
||||||
|
"@angular/platform-browser": "^19.2.0",
|
||||||
|
"@angular/platform-browser-dynamic": "^19.2.0",
|
||||||
|
"@angular/router": "^19.2.0",
|
||||||
|
"rxjs": "~7.8.0",
|
||||||
|
"tslib": "^2.3.0",
|
||||||
|
"zone.js": "~0.15.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@angular-devkit/build-angular": "^19.2.0",
|
||||||
|
"@angular/cli": "^19.2.0",
|
||||||
|
"@angular/compiler-cli": "^19.2.0",
|
||||||
|
"@types/jasmine": "~5.1.0",
|
||||||
|
"jasmine-core": "~5.6.0",
|
||||||
|
"karma": "~6.4.0",
|
||||||
|
"karma-chrome-launcher": "~3.2.0",
|
||||||
|
"karma-coverage": "~2.2.0",
|
||||||
|
"karma-jasmine": "~5.1.0",
|
||||||
|
"karma-jasmine-html-reporter": "~2.1.0",
|
||||||
|
"typescript": "~5.7.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
29
src/app/app-routing.module.ts
Normal file
29
src/app/app-routing.module.ts
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
|
|
||||||
|
import { UserListComponent } from './components/users/user-list/user-list.component';
|
||||||
|
|
||||||
|
import { CoursListComponent } from './components/cours/cours-list/cours-list.component';
|
||||||
|
import { CoursDetailComponent } from './components/cours/cours-detail/cours-detail.component';
|
||||||
|
import { CoursFormComponent } from './components/cours/cours-form/cours-form.component';
|
||||||
|
|
||||||
|
import { GroupFormComponent } from './components/groups/group-form/group-form.component';
|
||||||
|
import { GroupDetailComponent } from './components/groups/group-detail/group-detail.component';
|
||||||
|
import { GroupListComponent } from './components/groups/group-list/group-list.component';
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{ path: 'cours/create', component: CoursFormComponent },
|
||||||
|
{ path: 'cours/:id/edit', component: CoursFormComponent },
|
||||||
|
{ path: 'cours/:id', component: CoursDetailComponent },
|
||||||
|
{ path: 'cours', component: CoursListComponent },
|
||||||
|
{ path: 'users', component: UserListComponent },
|
||||||
|
{ path: 'groups/create', component: GroupFormComponent },
|
||||||
|
{ path: 'groups/:id', component: GroupDetailComponent },
|
||||||
|
{ path: 'groups', component: GroupListComponent }
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [RouterModule.forRoot(routes)],
|
||||||
|
exports: [RouterModule]
|
||||||
|
})
|
||||||
|
export class AppRoutingModule { }
|
||||||
0
src/app/app.component.css
Normal file
0
src/app/app.component.css
Normal file
3
src/app/app.component.html
Normal file
3
src/app/app.component.html
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<div class="container mt-4">
|
||||||
|
<router-outlet></router-outlet>
|
||||||
|
</div>
|
||||||
35
src/app/app.component.spec.ts
Normal file
35
src/app/app.component.spec.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
|
||||||
|
describe('AppComponent', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [
|
||||||
|
RouterModule.forRoot([])
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
AppComponent
|
||||||
|
],
|
||||||
|
}).compileComponents();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create the app', () => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
const app = fixture.componentInstance;
|
||||||
|
expect(app).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should have as title 'project'`, () => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
const app = fixture.componentInstance;
|
||||||
|
expect(app.title).toEqual('project');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render title', () => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
const compiled = fixture.nativeElement as HTMLElement;
|
||||||
|
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, project');
|
||||||
|
});
|
||||||
|
});
|
||||||
11
src/app/app.component.ts
Normal file
11
src/app/app.component.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-root',
|
||||||
|
templateUrl: './app.component.html',
|
||||||
|
standalone: false,
|
||||||
|
styleUrl: './app.component.css'
|
||||||
|
})
|
||||||
|
export class AppComponent {
|
||||||
|
title = 'project';
|
||||||
|
}
|
||||||
40
src/app/app.module.ts
Normal file
40
src/app/app.module.ts
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
|
||||||
|
import { AppRoutingModule } from './app-routing.module';
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
|
||||||
|
import { ReactiveFormsModule, FormsModule } from '@angular/forms';
|
||||||
|
|
||||||
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
|
|
||||||
|
import { UserListComponent } from './components/users/user-list/user-list.component';
|
||||||
|
import { CoursListComponent } from './components/cours/cours-list/cours-list.component';
|
||||||
|
import { CoursDetailComponent } from './components/cours/cours-detail/cours-detail.component';
|
||||||
|
import { CoursFormComponent } from './components/cours/cours-form/cours-form.component';
|
||||||
|
import { GroupFormComponent } from './components/groups/group-form/group-form.component';
|
||||||
|
import { GroupDetailComponent } from './components/groups/group-detail/group-detail.component';
|
||||||
|
import { GroupListComponent } from './components/groups/group-list/group-list.component';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
AppComponent,
|
||||||
|
UserListComponent,
|
||||||
|
CoursListComponent,
|
||||||
|
CoursDetailComponent,
|
||||||
|
CoursFormComponent,
|
||||||
|
GroupFormComponent,
|
||||||
|
GroupDetailComponent,
|
||||||
|
GroupListComponent
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
BrowserModule,
|
||||||
|
AppRoutingModule,
|
||||||
|
HttpClientModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
FormsModule
|
||||||
|
],
|
||||||
|
providers: [],
|
||||||
|
bootstrap: [AppComponent]
|
||||||
|
})
|
||||||
|
export class AppModule { }
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
<div *ngIf="cours">
|
||||||
|
<h2>{{ cours.name }}</h2>
|
||||||
|
<p>{{ cours.description }}</p>
|
||||||
|
<a [routerLink]="['/cours', cours.id, 'edit']">Modifier</a>
|
||||||
|
<a routerLink="/cours">Retour à la liste</a>
|
||||||
|
</div>
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { CoursDetailComponent } from './cours-detail.component';
|
||||||
|
|
||||||
|
describe('CoursDetailComponent', () => {
|
||||||
|
let component: CoursDetailComponent;
|
||||||
|
let fixture: ComponentFixture<CoursDetailComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [CoursDetailComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(CoursDetailComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
|
||||||
|
import { CoursService } from '../../../services/cours.service';
|
||||||
|
import { Cours } from '../../../models/cours';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-cours-detail',
|
||||||
|
standalone: false,
|
||||||
|
templateUrl: './cours-detail.component.html',
|
||||||
|
styleUrl: './cours-detail.component.css'
|
||||||
|
})
|
||||||
|
export class CoursDetailComponent implements OnInit {
|
||||||
|
cours?: Cours;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private route: ActivatedRoute,
|
||||||
|
private coursService: CoursService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
const id = Number(this.route.snapshot.paramMap.get('id'));
|
||||||
|
this.coursService.getById(id).subscribe(data => this.cours = data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<h2>{{ isEdit ? 'Modifier le cours' : 'Ajouter un cours' }}</h2>
|
||||||
|
<form [formGroup]="coursForm" (ngSubmit)="onSubmit()">
|
||||||
|
<label>Nom :</label>
|
||||||
|
<input formControlName="name" required>
|
||||||
|
<label>Description :</label>
|
||||||
|
<textarea formControlName="description" required></textarea>
|
||||||
|
<button type="submit">{{ isEdit ? 'Mettre à jour' : 'Ajouter' }}</button>
|
||||||
|
<a routerLink="/cours">Annuler</a>
|
||||||
|
</form>
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { CoursFormComponent } from './cours-form.component';
|
||||||
|
|
||||||
|
describe('CoursFormComponent', () => {
|
||||||
|
let component: CoursFormComponent;
|
||||||
|
let fixture: ComponentFixture<CoursFormComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [CoursFormComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(CoursFormComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
55
src/app/components/cours/cours-form/cours-form.component.ts
Normal file
55
src/app/components/cours/cours-form/cours-form.component.ts
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
|
|
||||||
|
import { CoursService } from '../../../services/cours.service';
|
||||||
|
import { Cours } from '../../../models/cours';
|
||||||
|
|
||||||
|
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-cours-form',
|
||||||
|
standalone: false,
|
||||||
|
templateUrl: './cours-form.component.html',
|
||||||
|
styleUrl: './cours-form.component.css'
|
||||||
|
})
|
||||||
|
export class CoursFormComponent implements OnInit {
|
||||||
|
coursForm: FormGroup;
|
||||||
|
isEdit = false;
|
||||||
|
coursId?: number;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private fb: FormBuilder,
|
||||||
|
private coursService: CoursService,
|
||||||
|
private route: ActivatedRoute,
|
||||||
|
private router: Router
|
||||||
|
) {
|
||||||
|
this.coursForm = this.fb.group({
|
||||||
|
name: ['', Validators.required],
|
||||||
|
description: ['', Validators.required]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.coursId = Number(this.route.snapshot.paramMap.get('id'));
|
||||||
|
this.isEdit = !!this.coursId;
|
||||||
|
if (this.isEdit) {
|
||||||
|
this.coursService.getById(this.coursId).subscribe(cours => {
|
||||||
|
this.coursForm.patchValue(cours);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmit() {
|
||||||
|
if (this.coursForm.valid) {
|
||||||
|
if (this.isEdit) {
|
||||||
|
this.coursService.update(this.coursId!, this.coursForm.value).subscribe(() => {
|
||||||
|
this.router.navigate(['/cours', this.coursId]);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.coursService.create(this.coursForm.value).subscribe(() => {
|
||||||
|
this.router.navigate(['/cours']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<h2>Liste des cours</h2>
|
||||||
|
<a routerLink="/cours/new">Ajouter un cours</a>
|
||||||
|
<ul>
|
||||||
|
<li *ngFor="let cours of coursList">
|
||||||
|
<a [routerLink]="['/cours', cours.id]">{{ cours.name }}</a>
|
||||||
|
<button [routerLink]="['/cours', cours.id, 'edit']">Modifier</button>
|
||||||
|
<button (click)="deleteCours(cours.id)">Supprimer</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { CoursListComponent } from './cours-list.component';
|
||||||
|
|
||||||
|
describe('CoursListComponent', () => {
|
||||||
|
let component: CoursListComponent;
|
||||||
|
let fixture: ComponentFixture<CoursListComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [CoursListComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(CoursListComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
26
src/app/components/cours/cours-list/cours-list.component.ts
Normal file
26
src/app/components/cours/cours-list/cours-list.component.ts
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
import { CoursService } from '../../../services/cours.service';
|
||||||
|
import { Cours } from '../../../models/cours';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-cours-list',
|
||||||
|
standalone: false,
|
||||||
|
templateUrl: './cours-list.component.html',
|
||||||
|
styleUrl: './cours-list.component.css'
|
||||||
|
})
|
||||||
|
export class CoursListComponent implements OnInit {
|
||||||
|
coursList: Cours[] = [];
|
||||||
|
|
||||||
|
constructor(private coursService: CoursService) {}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.coursService.getAll().subscribe(data => this.coursList = data);
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteCours(id: number) {
|
||||||
|
this.coursService.delete(id).subscribe(() => {
|
||||||
|
this.coursList = this.coursList.filter(c => c.id !== id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
<div *ngIf="group">
|
||||||
|
<h2>{{ group.name }}</h2>
|
||||||
|
<p>{{ group.description }}</p>
|
||||||
|
|
||||||
|
<h3>Membres</h3>
|
||||||
|
<ul>
|
||||||
|
<li *ngFor="let user of group.members">
|
||||||
|
{{ getUserName(user) }}
|
||||||
|
<button (click)="removeUser(user)">Supprimer</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<input type="number" [(ngModel)]="userIdToAdd" placeholder="ID utilisateur">
|
||||||
|
<button (click)="addUser()">Ajouter utilisateur</button>
|
||||||
|
|
||||||
|
<h3>Cours</h3>
|
||||||
|
<ul>
|
||||||
|
<li *ngFor="let cours of group.cours">
|
||||||
|
{{ getCoursName(cours) }}
|
||||||
|
<button (click)="removeCours(cours)">Supprimer</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<input type="number" [(ngModel)]="coursIdToAdd" placeholder="ID cours">
|
||||||
|
<button (click)="addCours()">Ajouter cours</button>
|
||||||
|
</div>
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { GroupDetailComponent } from './group-detail.component';
|
||||||
|
|
||||||
|
describe('GroupDetailComponent', () => {
|
||||||
|
let component: GroupDetailComponent;
|
||||||
|
let fixture: ComponentFixture<GroupDetailComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [GroupDetailComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(GroupDetailComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
|
||||||
|
import { GroupService } from '../../../services/group.service';
|
||||||
|
import { Group } from '../../../models/group';
|
||||||
|
|
||||||
|
import { UserService } from '../../../services/user.service';
|
||||||
|
import { User } from '../../../models/user';
|
||||||
|
|
||||||
|
import { CoursService } from '../../../services/cours.service';
|
||||||
|
import { Cours } from '../../../models/cours';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-group-detail',
|
||||||
|
standalone: false,
|
||||||
|
templateUrl: './group-detail.component.html',
|
||||||
|
styleUrl: './group-detail.component.css'
|
||||||
|
})
|
||||||
|
export class GroupDetailComponent implements OnInit {
|
||||||
|
group?: Group;
|
||||||
|
userIdToAdd: number = 0;
|
||||||
|
coursIdToAdd: number = 0;
|
||||||
|
users: User[] = [];
|
||||||
|
coursList: Cours[] = [];
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private route: ActivatedRoute,
|
||||||
|
private groupService: GroupService,
|
||||||
|
private userService: UserService,
|
||||||
|
private coursService: CoursService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
const id = Number(this.route.snapshot.paramMap.get('id'));
|
||||||
|
this.groupService.getById(id).subscribe(data => this.group = data);
|
||||||
|
this.userService.getAll().subscribe(data => this.users = data);
|
||||||
|
this.coursService.getAll().subscribe(data => this.coursList = data);
|
||||||
|
}
|
||||||
|
|
||||||
|
getUserName(userId: number) {
|
||||||
|
const user = this.users.find(u => u.id === userId);
|
||||||
|
return user ? user.first_name + ' ' + user.last_name : userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
getCoursName(coursId: number) {
|
||||||
|
const cours = this.coursList.find(c => c.id === coursId);
|
||||||
|
return cours ? cours.name : coursId;
|
||||||
|
}
|
||||||
|
|
||||||
|
addUser() {
|
||||||
|
if (this.group && this.userIdToAdd) {
|
||||||
|
this.groupService.addUserToGroup(this.group.id, this.userIdToAdd).subscribe(() => {
|
||||||
|
this.ngOnInit();
|
||||||
|
this.userIdToAdd = 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
removeUser(userId: number) {
|
||||||
|
if (this.group) {
|
||||||
|
this.groupService.removeUserFromGroup(this.group.id, userId).subscribe(() => {
|
||||||
|
this.ngOnInit();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addCours() {
|
||||||
|
if (this.group && this.coursIdToAdd) {
|
||||||
|
this.groupService.addCoursToGroup(this.group.id, this.coursIdToAdd).subscribe(() => {
|
||||||
|
this.ngOnInit();
|
||||||
|
this.coursIdToAdd = 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
removeCours(coursId: number) {
|
||||||
|
if (this.group) {
|
||||||
|
this.groupService.removeCoursFromGroup(this.group.id, coursId).subscribe(() => {
|
||||||
|
this.ngOnInit();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<h2>Créer un groupe</h2>
|
||||||
|
<form [formGroup]="groupForm" (ngSubmit)="onSubmit()">
|
||||||
|
<label>Nom :</label>
|
||||||
|
<input formControlName="name" required>
|
||||||
|
<label>Description :</label>
|
||||||
|
<textarea formControlName="description" required></textarea>
|
||||||
|
<button type="submit">Créer</button>
|
||||||
|
<a routerLink="/groups">Annuler</a>
|
||||||
|
</form>
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { GroupFormComponent } from './group-form.component';
|
||||||
|
|
||||||
|
describe('GroupFormComponent', () => {
|
||||||
|
let component: GroupFormComponent;
|
||||||
|
let fixture: ComponentFixture<GroupFormComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [GroupFormComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(GroupFormComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
33
src/app/components/groups/group-form/group-form.component.ts
Normal file
33
src/app/components/groups/group-form/group-form.component.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||||
|
import { GroupService } from '../../../services/group.service';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-group-form',
|
||||||
|
standalone: false,
|
||||||
|
templateUrl: './group-form.component.html',
|
||||||
|
styleUrl: './group-form.component.css'
|
||||||
|
})
|
||||||
|
export class GroupFormComponent {
|
||||||
|
groupForm: FormGroup;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private fb: FormBuilder,
|
||||||
|
private groupService: GroupService,
|
||||||
|
private router: Router
|
||||||
|
) {
|
||||||
|
this.groupForm = this.fb.group({
|
||||||
|
name: ['', Validators.required],
|
||||||
|
description: ['', Validators.required]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmit() {
|
||||||
|
if (this.groupForm.valid) {
|
||||||
|
this.groupService.create(this.groupForm.value).subscribe(() => {
|
||||||
|
this.router.navigate(['/groups']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
<h2>Liste des groupes</h2>
|
||||||
|
<a routerLink="/groups/create">Créer un groupe</a>
|
||||||
|
<ul>
|
||||||
|
<li *ngFor="let group of groups">
|
||||||
|
<a [routerLink]="['/groups', group.id]">{{ group.name }}</a>
|
||||||
|
<button (click)="deleteGroup(group.id)">Supprimer</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { GroupListComponent } from './group-list.component';
|
||||||
|
|
||||||
|
describe('GroupListComponent', () => {
|
||||||
|
let component: GroupListComponent;
|
||||||
|
let fixture: ComponentFixture<GroupListComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [GroupListComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(GroupListComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
25
src/app/components/groups/group-list/group-list.component.ts
Normal file
25
src/app/components/groups/group-list/group-list.component.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { GroupService } from '../../../services/group.service';
|
||||||
|
import { Group } from '../../../models/group';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-group-list',
|
||||||
|
standalone: false,
|
||||||
|
templateUrl: './group-list.component.html',
|
||||||
|
styleUrl: './group-list.component.css'
|
||||||
|
})
|
||||||
|
export class GroupListComponent implements OnInit {
|
||||||
|
groups: Group[] = [];
|
||||||
|
|
||||||
|
constructor(private groupService: GroupService) {}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.groupService.getAll().subscribe(data => this.groups = data);
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteGroup(id: number) {
|
||||||
|
this.groupService.delete(id).subscribe(() => {
|
||||||
|
this.groups = this.groups.filter(g => g.id !== id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
<h2>Liste des utilisateurs</h2>
|
||||||
|
<ul>
|
||||||
|
<li *ngFor="let user of users">
|
||||||
|
{{ user.first_name }} {{ user.last_name }} - {{ user.role }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { UserListComponent } from './user-list.component';
|
||||||
|
|
||||||
|
describe('UserListComponent', () => {
|
||||||
|
let component: UserListComponent;
|
||||||
|
let fixture: ComponentFixture<UserListComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [UserListComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(UserListComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
22
src/app/components/users/user-list/user-list.component.ts
Normal file
22
src/app/components/users/user-list/user-list.component.ts
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
import { UserService } from './../../../services/user.service';
|
||||||
|
import { User } from './../../../models/user';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-user-list',
|
||||||
|
standalone: false,
|
||||||
|
templateUrl: './user-list.component.html',
|
||||||
|
styleUrl: './user-list.component.css'
|
||||||
|
})
|
||||||
|
export class UserListComponent implements OnInit {
|
||||||
|
|
||||||
|
users: User[] = [];
|
||||||
|
|
||||||
|
constructor(private userService: UserService) {}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.userService.getAll().subscribe(data => this.users = data);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
5
src/app/models/cours.ts
Normal file
5
src/app/models/cours.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
export interface Cours {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
7
src/app/models/group.ts
Normal file
7
src/app/models/group.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
export interface Group {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
members: number[];
|
||||||
|
cours: number[];
|
||||||
|
}
|
||||||
7
src/app/models/user.ts
Normal file
7
src/app/models/user.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
export interface User {
|
||||||
|
id: number;
|
||||||
|
first_name: string;
|
||||||
|
last_name: string;
|
||||||
|
email: string;
|
||||||
|
role: 'admin' | 'student';
|
||||||
|
}
|
||||||
16
src/app/services/cours.service.spec.ts
Normal file
16
src/app/services/cours.service.spec.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { CoursService } from './cours.service';
|
||||||
|
|
||||||
|
describe('CoursService', () => {
|
||||||
|
let service: CoursService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(CoursService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
34
src/app/services/cours.service.ts
Normal file
34
src/app/services/cours.service.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
|
import { Cours } from '../models/cours';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class CoursService {
|
||||||
|
private apiUrl = 'http://localhost:3000/cours';
|
||||||
|
|
||||||
|
constructor(private http: HttpClient) {}
|
||||||
|
|
||||||
|
getAll(): Observable<Cours[]> {
|
||||||
|
return this.http.get<Cours[]>(this.apiUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
getById(id: number): Observable<Cours> {
|
||||||
|
return this.http.get<Cours>(`${this.apiUrl}/${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
create(cours: Cours): Observable<any> {
|
||||||
|
return this.http.post(this.apiUrl, cours);
|
||||||
|
}
|
||||||
|
|
||||||
|
update(id: number, cours: Cours): Observable<any> {
|
||||||
|
return this.http.put(`${this.apiUrl}/${id}`, cours);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(id: number): Observable<any> {
|
||||||
|
return this.http.delete(`${this.apiUrl}/${id}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
16
src/app/services/group.service.spec.ts
Normal file
16
src/app/services/group.service.spec.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { GroupService } from './group.service';
|
||||||
|
|
||||||
|
describe('GroupService', () => {
|
||||||
|
let service: GroupService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(GroupService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
50
src/app/services/group.service.ts
Normal file
50
src/app/services/group.service.ts
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
|
import { Group } from '../models/group';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class GroupService {
|
||||||
|
private apiUrl = 'http://localhost:3000/groups';
|
||||||
|
|
||||||
|
constructor(private http: HttpClient) {}
|
||||||
|
|
||||||
|
getAll(): Observable<Group[]> {
|
||||||
|
return this.http.get<Group[]>(this.apiUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
getById(id: number): Observable<Group> {
|
||||||
|
return this.http.get<Group>(`${this.apiUrl}/${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
create(group: Partial<Group>): Observable<any> {
|
||||||
|
return this.http.post(this.apiUrl, group);
|
||||||
|
}
|
||||||
|
|
||||||
|
update(id: number, group: Partial<Group>): Observable<any> {
|
||||||
|
return this.http.put(`${this.apiUrl}/${id}`, group);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(id: number): Observable<any> {
|
||||||
|
return this.http.delete(`${this.apiUrl}/${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
addUserToGroup(groupId: number, userId: number): Observable<any> {
|
||||||
|
return this.http.post(`${this.apiUrl}/${groupId}/users`, { userId });
|
||||||
|
}
|
||||||
|
|
||||||
|
removeUserFromGroup(groupId: number, userId: number): Observable<any> {
|
||||||
|
return this.http.delete(`${this.apiUrl}/${groupId}/users/${userId}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
addCoursToGroup(groupId: number, coursId: number): Observable<any> {
|
||||||
|
return this.http.post(`${this.apiUrl}/${groupId}/cours`, { coursId: coursId });
|
||||||
|
}
|
||||||
|
|
||||||
|
removeCoursFromGroup(groupId: number, coursId: number): Observable<any> {
|
||||||
|
return this.http.delete(`${this.apiUrl}/${groupId}/cours/${coursId}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
16
src/app/services/user.service.spec.ts
Normal file
16
src/app/services/user.service.spec.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { UserService } from './user.service';
|
||||||
|
|
||||||
|
describe('UserService', () => {
|
||||||
|
let service: UserService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(UserService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
34
src/app/services/user.service.ts
Normal file
34
src/app/services/user.service.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
|
import { User } from './../models/user';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class UserService {
|
||||||
|
private apiUrl = 'http://localhost:3000/users';
|
||||||
|
|
||||||
|
constructor(private http: HttpClient) {}
|
||||||
|
|
||||||
|
getAll(): Observable<User[]> {
|
||||||
|
return this.http.get<User[]>(this.apiUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
getById(id: number): Observable<User> {
|
||||||
|
return this.http.get<User>(`${this.apiUrl}/${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
create(user: User): Observable<any> {
|
||||||
|
return this.http.post(this.apiUrl, user);
|
||||||
|
}
|
||||||
|
|
||||||
|
update(id: number, user: User): Observable<any> {
|
||||||
|
return this.http.put(`${this.apiUrl}/${id}`, user);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(id: number): Observable<any> {
|
||||||
|
return this.http.delete(`${this.apiUrl}/${id}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/index.html
Normal file
15
src/index.html
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Project</title>
|
||||||
|
<base href="/">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap" rel="stylesheet">
|
||||||
|
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
<body class="mat-typography">
|
||||||
|
<app-root></app-root>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
7
src/main.ts
Normal file
7
src/main.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
|
import { AppModule } from './app/app.module';
|
||||||
|
|
||||||
|
platformBrowserDynamic().bootstrapModule(AppModule, {
|
||||||
|
ngZoneEventCoalescing: true,
|
||||||
|
})
|
||||||
|
.catch(err => console.error(err));
|
||||||
4
src/styles.css
Normal file
4
src/styles.css
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
/* 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; }
|
||||||
15
tsconfig.app.json
Normal file
15
tsconfig.app.json
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
|
||||||
|
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
|
||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "./out-tsc/app",
|
||||||
|
"types": []
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"src/main.ts"
|
||||||
|
],
|
||||||
|
"include": [
|
||||||
|
"src/**/*.d.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
27
tsconfig.json
Normal file
27
tsconfig.json
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
|
||||||
|
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
|
||||||
|
{
|
||||||
|
"compileOnSave": false,
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "./dist/out-tsc",
|
||||||
|
"strict": true,
|
||||||
|
"noImplicitOverride": true,
|
||||||
|
"noPropertyAccessFromIndexSignature": true,
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"importHelpers": true,
|
||||||
|
"target": "ES2022",
|
||||||
|
"module": "ES2022"
|
||||||
|
},
|
||||||
|
"angularCompilerOptions": {
|
||||||
|
"enableI18nLegacyMessageIdFormat": false,
|
||||||
|
"strictInjectionParameters": true,
|
||||||
|
"strictInputAccessModifiers": true,
|
||||||
|
"strictTemplates": true
|
||||||
|
}
|
||||||
|
}
|
||||||
15
tsconfig.spec.json
Normal file
15
tsconfig.spec.json
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
|
||||||
|
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
|
||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "./out-tsc/spec",
|
||||||
|
"types": [
|
||||||
|
"jasmine"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"src/**/*.spec.ts",
|
||||||
|
"src/**/*.d.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue