diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..3941ae9 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,24 @@ +# Contributing + +Thank you for contributing. + +## Workflow + +1. Create a feature branch +2. Keep changes focused and minimal +3. Run build/tests before submitting +4. Open a pull request with clear description + +## Coding Guidelines + +- Use strict TypeScript typing +- Keep components small and focused +- Prefer feature module organization +- Follow existing naming conventions + +## Validation + +```bash +npm run build +npm run test +``` diff --git a/README.md b/README.md index d08b1a8..5e918ac 100644 --- a/README.md +++ b/README.md @@ -1,264 +1,156 @@ -## Angular Training +# Formation Angular -NVM Install For Windows -https://github.com/coreybutler/nvm-windows/releases/download/1.2.2/nvm-setup.zip -``` -Installation Steps : - 1-Download and run the nvm-setup.exe installer - 2-Select the NVM installation path (e.g., C:\nvm) - 3-Select the Node.js installation path (e.g., C:\nodejs) - 4-Confirm the installation -``` -NVM Install For Linux/MacOS -Using the Installation Script +![Angular 19.2](https://img.shields.io/badge/Angular-19.2-dd0031?logo=angular&logoColor=white) +![Angular 21 Ready](https://img.shields.io/badge/Angular-21%20ready-0f172a?logo=angular) +![Status](https://img.shields.io/badge/status-active-success) -Open a terminal and execute one of the following commands: -``` -curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash -``` -Or: -``` -wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash -``` -Version compatibility : https://angular.dev/reference/versions -``` -1 - working with angular 13/14 : - nvm use 14.15 - npm i @angular/cli@13 -2 - working with angular 21 - nouveatés depuis la version 15 - 21 - * Les Standalone Components - * Les Signals - * Les Signal Forms (expérimental) - * Nouvelle syntaxe de contrôle de flux (@if, @for, @switch - nvm use 22 ou 24 - npm i @angular/cli@21 -``` -1️⃣ Créer une application Angular -``` -ng new formation-angular -cd formation-angular -ng serve -``` -use backend api : -``` -https://github.com/Invivoo/spring-crud -``` -test : -```sh - http://localhost:4200 -``` -Project structure version 13/14 -``` - . - ├── nodes_modules - └── src - ├── app - │   ├── app.component.css - │   ├── app.component.html - │   ├── app.component.spec.ts - │   ├── app.component.ts - │   ├── app.module.ts - │   ├── app.routing.module.ts - | - └── index.html - └── main.ts - └── styles.css - └── test.ts - ├── angular.json - ├── package.json - ├── package-lock.json - ├── README.md - ├── tsconfig.app.json - ├── tsconfig.app - ├── tsconfig.spec.json +Training repository to practice Angular fundamentals (module-based style) and modern Angular concepts (up to Angular 21). -``` +## Quick Start -Project structure version 21 +```bash +git clone https://github.com/Invivoo/formation-angular.git +cd formation-angular +npm install +npm run start ``` - . - ├── nodes_modules - └── src - ├── app - │   ├── app.config.ts - │   ├── app.css - │   ├── app.html - │   ├── app.routes.ts - │   ├── app.spec.ts - │   └── app.ts - └── index.html - └── main.ts - └── styles.css - ├── angular.json - ├── package.json - ├── package-lock.json - ├── README.md - ├── tsconfig.app.json - ├── tsconfig.app - ├── tsconfig.spec.json -``` +Open `http://localhost:4200`. -2️⃣ Services api and crud components +> Backend API examples: +> - https://github.com/Invivoo/spring-crud +> - https://github.com/Invivoo/node-crud-api -1 add module users on app/ directory -``` -ng g module users --routing -``` -2 add model folder : -``` -add user.model.ts -``` -3 add a new component : -``` -ng g component crud -``` -4 add services folder : -``` -ng g service users -``` -``` -└── src - ├── app - │   ├── users - │   ├── model - │   ├── user.model.ts - │   ├── services - │   ├── users.service.ts - │   ├── crud - │   ├── crud.component.css - │   ├── crud.component.html - │   ├── crud.component.ts - │   ├── users.module.ts - │   ├── users-routing.module.ts - │   ├── app.component.html - │   ├── app.component.spec.ts - │   ├── app.component.ts - │   ├── app.module.ts - │   ├── app.routing.module.ts -``` -- install bootstrap - ``` - npm install --save bootstrap - ``` - - update styles.css - ``` add - @import "bootstrap/dist/css/bootstrap.min.css"; - ``` -3️⃣ users.serice.ts -```ts -import { Injectable } from '@angular/core'; -import {HttpClient} from '@angular/common/http'; -import {Observable} from 'rxjs'; -import {UserModel} from '../model/user.model'; +--- -const baseUrl = 'http://localhost:8081/api/v1/employees'; +## Table of Contents -@Injectable({ - providedIn: 'root' -}) -export class UsersService { +- [Prerequisites](#prerequisites) +- [Setup](#setup) +- [Project Structure](#project-structure) +- [Development Steps](#development-steps) +- [Conventions and Best Practices](#conventions-and-best-practices) +- [Troubleshooting](#troubleshooting) +- [Contributing](#contributing) +- [Resources](#resources) - constructor(private http: HttpClient) {} +## Prerequisites - getUsers(): Observable { - return this.http.get(baseUrl); - } +- Node.js managed with NVM +- npm +- Angular CLI - create(data: any): Observable { - return this.http.post(baseUrl, data); - } +### NVM installation - update(id: any, data: any): Observable { - return this.http.put(`${baseUrl}/${id}`, data); - } +- Windows: https://github.com/coreybutler/nvm-windows/releases +- Linux/macOS: - delete(id: any): Observable { - return this.http.delete(`${baseUrl}/${id}`); - } +```bash +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash +``` - findByEmail(email: any): Observable { - return this.http.get(`${baseUrl}?email=${email}`); - } -} +or +```bash +wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash ``` -- crud.component.ts -```ts - export class CrudComponent implements OnInit { - userList: UserModel[] = []; +### Angular version compatibility - constructor(private usersService: UsersService) {} +Reference: https://angular.dev/reference/versions - ngOnInit(): void { - this.usersService.getUsers().subscribe(rep => { - this.userList = rep - }); - } -. -. -. -``` -- add a user-card component - add : ```@Input() user: UserModel;``` - -- user-card component html : -```html --
-
USER
-
-
{{ user.firstName }} {{ user.lastName }}
-

- {{ user.email }} -

-
-
-``` -- crud.component.html -```html -
- -
-``` -- app.compoent.html - add : - ```html - - -``` +```bash +# Angular 13/14 style training +nvm use 14.15 +npm install -g @angular/cli@14 + +# Secure baseline used in this repository +nvm use 22 +npm install -g @angular/cli@19 -- routing app.routing.module.ts -```ts -const routes: Routes = [ - {path: '', component: AppComponent}, - {path: 'users', loadChildren: () => import('../users/users.module').then(m => m.UsersModule)} - ]; +# Angular 21 experimentation +nvm use 22 +npm install -g @angular/cli@21 ``` -- routing users.routing.module.ts -```ts -const routes: Routes = [ - {path: 'all', component: CrudComponent}, - {path: 'create', component: AddUserComponent}, -]; + +## Setup + +```bash +npm install +npm run start ``` +## Project Structure + +```text +. +├── README.md +├── SETUP.md +├── CONTRIBUTING.md +├── angular.json +├── package.json +├── tsconfig.json +└── src + ├── index.html + ├── main.ts + ├── styles.css + └── app + ├── app.component.ts + ├── app.component.html + ├── app.component.css + ├── app.module.ts + ├── app-routing.module.ts + └── users + ├── users.module.ts + ├── users-routing.module.ts + ├── model/user.model.ts + ├── services/users.service.ts + ├── crud + │ ├── crud.component.ts + │ ├── crud.component.html + │ └── crud.component.css + └── user-card + ├── user-card.component.ts + ├── user-card.component.html + └── user-card.component.css +``` + +## Development Steps + +1. Create an Angular app scaffold. +2. Add a `users` feature module with routing. +3. Add a typed `UserModel`. +4. Add `UsersService` for API CRUD operations. +5. Add `CrudComponent` and `UserCardComponent`. +6. Add Bootstrap global styles. +7. Connect navbar routing (`/users/all`, `/users/create`). + +## Conventions and Best Practices + +- Use strict TypeScript typing (`Partial`, explicit interfaces). +- Keep feature code grouped by module (`users/*`). +- Keep services thin and reusable. +- Use presentational components (`user-card`) for rendering. +- Avoid business logic in templates. +- Keep routes explicit and predictable. + +## Troubleshooting + +- **`ng: command not found`**: install Angular CLI globally (`npm i -g @angular/cli`). +- **Port 4200 already used**: + ```bash + npm run start -- --port 4300 + ``` +- **Backend connection refused**: ensure API is running on `http://localhost:8081` or update service base URL. +- **Node version mismatch**: run `nvm use` with the expected version. + +## Contributing + +Please read [CONTRIBUTING.md](./CONTRIBUTING.md) before opening a PR. + +## Resources +- Angular docs: https://angular.dev +- RxJS docs: https://rxjs.dev +- Bootstrap docs: https://getbootstrap.com/docs +- Setup guide: [SETUP.md](./SETUP.md) diff --git a/SETUP.md b/SETUP.md new file mode 100644 index 0000000..b20f156 --- /dev/null +++ b/SETUP.md @@ -0,0 +1,42 @@ +# Setup Guide + +## 1) Install prerequisites + +- Install NVM +- Install Node.js with NVM +- Install Angular CLI + +```bash +nvm install 22 +nvm use 22 +npm install -g @angular/cli@19 +``` + +## 2) Install dependencies + +```bash +npm install +``` + +## 3) Start the app + +```bash +npm run start +``` + +Open `http://localhost:4200`. + +## 4) Backend API + +Run one backend API before testing CRUD calls: + +- https://github.com/Invivoo/spring-crud +- https://github.com/Invivoo/node-crud-api + +Default API URL in this project: `http://localhost:8081/api/v1/employees`. + +## 5) Build + +```bash +npm run build +``` diff --git a/angular.json b/angular.json new file mode 100644 index 0000000..4afb588 --- /dev/null +++ b/angular.json @@ -0,0 +1,75 @@ +{ + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "newProjectRoot": "projects", + "projects": { + "formation-angular": { + "projectType": "application", + "schematics": {}, + "root": "", + "sourceRoot": "src", + "prefix": "app", + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:browser", + "options": { + "outputPath": "dist/formation-angular", + "index": "src/index.html", + "main": "src/main.ts", + "tsConfig": "tsconfig.json", + "assets": [], + "styles": [ + "src/styles.css" + ], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "600kb", + "maximumError": "1mb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "builder": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "browserTarget": "formation-angular:build:production" + }, + "development": { + "browserTarget": "formation-angular:build:development" + } + }, + "defaultConfiguration": "development" + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "main": "src/test.ts", + "tsConfig": "tsconfig.spec.json", + "karmaConfig": "karma.conf.js", + "styles": [ + "src/styles.css" + ], + "scripts": [] + } + } + } + } + } +} diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 0000000..e81e5fa --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,34 @@ +// Karma configuration +module.exports = function (config) { + config.set({ + basePath: '', + frameworks: ['jasmine', '@angular-devkit/build-angular'], + plugins: [ + require('karma-jasmine'), + require('karma-chrome-launcher'), + require('karma-jasmine-html-reporter'), + require('karma-coverage'), + require('@angular-devkit/build-angular/plugins/karma') + ], + client: { + jasmine: {}, + clearContext: false + }, + jasmineHtmlReporter: { + suppressAll: true + }, + coverageReporter: { + dir: require('path').join(__dirname, './coverage/formation-angular'), + subdir: '.', + reporters: [{ type: 'html' }, { type: 'text-summary' }] + }, + reporters: ['progress', 'kjhtml'], + port: 9876, + colors: true, + logLevel: config.LOG_INFO, + autoWatch: true, + browsers: ['Chrome'], + singleRun: false, + restartOnFileChange: true + }); +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..7d6f9a3 --- /dev/null +++ b/package.json @@ -0,0 +1,40 @@ +{ + "name": "formation-angular", + "version": "1.0.0", + "private": true, + "description": "Angular training workspace", + "scripts": { + "ng": "ng", + "start": "ng serve", + "build": "ng build", + "test": "ng test --watch=false --browsers=ChromeHeadless", + "lint": "echo \"Linting is not configured for this training scaffold.\"" + }, + "dependencies": { + "@angular/animations": "^19.2.20", + "@angular/common": "^19.2.20", + "@angular/compiler": "^19.2.20", + "@angular/core": "^19.2.20", + "@angular/forms": "^19.2.20", + "@angular/platform-browser": "^19.2.20", + "@angular/platform-browser-dynamic": "^19.2.20", + "@angular/router": "^19.2.20", + "bootstrap": "^5.3.3", + "rxjs": "^7.5.0", + "tslib": "^2.3.0", + "zone.js": "~0.15.0" + }, + "devDependencies": { + "@angular-devkit/build-angular": "^19.2.20", + "@angular/cli": "^19.2.20", + "@angular/compiler-cli": "^19.2.20", + "@types/jasmine": "~4.0.0", + "jasmine-core": "~4.3.0", + "karma": "~6.4.0", + "karma-chrome-launcher": "~3.1.0", + "karma-coverage": "~2.2.0", + "karma-jasmine": "~5.1.0", + "karma-jasmine-html-reporter": "~2.0.0", + "typescript": "~5.7.2" + } +} diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts new file mode 100644 index 0000000..1444367 --- /dev/null +++ b/src/app/app-routing.module.ts @@ -0,0 +1,17 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; + +const routes: Routes = [ + { path: '', redirectTo: 'users/all', pathMatch: 'full' }, + { + path: 'users', + loadChildren: () => import('./users/users.module').then((m) => m.UsersModule) + }, + { path: '**', redirectTo: 'users/all' } +]; + +@NgModule({ + imports: [RouterModule.forRoot(routes)], + exports: [RouterModule] +}) +export class AppRoutingModule {} diff --git a/src/app/app.component.css b/src/app/app.component.css new file mode 100644 index 0000000..5d4e87f --- /dev/null +++ b/src/app/app.component.css @@ -0,0 +1,3 @@ +:host { + display: block; +} diff --git a/src/app/app.component.html b/src/app/app.component.html new file mode 100644 index 0000000..fa4d667 --- /dev/null +++ b/src/app/app.component.html @@ -0,0 +1,17 @@ + + +
+ +
diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts new file mode 100644 index 0000000..98e8054 --- /dev/null +++ b/src/app/app.component.spec.ts @@ -0,0 +1,25 @@ +import { TestBed } from '@angular/core/testing'; +import { RouterTestingModule } from '@angular/router/testing'; + +import { AppComponent } from './app.component'; + +describe('AppComponent', () => { + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [AppComponent], + imports: [RouterTestingModule] + }).compileComponents(); + }); + + it('should create the app', () => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.componentInstance; + expect(app).toBeTruthy(); + }); + + it('should expose application title', () => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.componentInstance; + expect(app.title).toBe('Formation Angular'); + }); +}); diff --git a/src/app/app.component.ts b/src/app/app.component.ts new file mode 100644 index 0000000..61e1e89 --- /dev/null +++ b/src/app/app.component.ts @@ -0,0 +1,11 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-root', + standalone: false, + templateUrl: './app.component.html', + styleUrls: ['./app.component.css'] +}) +export class AppComponent { + readonly title = 'Formation Angular'; +} diff --git a/src/app/app.module.ts b/src/app/app.module.ts new file mode 100644 index 0000000..2e01f9d --- /dev/null +++ b/src/app/app.module.ts @@ -0,0 +1,14 @@ +import { NgModule } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; +import { HttpClientModule } from '@angular/common/http'; + +import { AppRoutingModule } from './app-routing.module'; +import { AppComponent } from './app.component'; + +@NgModule({ + declarations: [AppComponent], + imports: [BrowserModule, HttpClientModule, AppRoutingModule], + providers: [], + bootstrap: [AppComponent] +}) +export class AppModule {} diff --git a/src/app/users/crud/crud.component.css b/src/app/users/crud/crud.component.css new file mode 100644 index 0000000..5d4e87f --- /dev/null +++ b/src/app/users/crud/crud.component.css @@ -0,0 +1,3 @@ +:host { + display: block; +} diff --git a/src/app/users/crud/crud.component.html b/src/app/users/crud/crud.component.html new file mode 100644 index 0000000..7b6fd97 --- /dev/null +++ b/src/app/users/crud/crud.component.html @@ -0,0 +1,13 @@ +
+

Users

+ +

Loading users...

+ + +
+
+ +
+

No users found.

+
+
diff --git a/src/app/users/crud/crud.component.ts b/src/app/users/crud/crud.component.ts new file mode 100644 index 0000000..d63ec9e --- /dev/null +++ b/src/app/users/crud/crud.component.ts @@ -0,0 +1,36 @@ +import { Component, OnInit } from '@angular/core'; + +import { UserModel } from '../model/user.model'; +import { UsersService } from '../services/users.service'; + +@Component({ + selector: 'app-crud', + standalone: false, + templateUrl: './crud.component.html', + styleUrls: ['./crud.component.css'] +}) +export class CrudComponent implements OnInit { + userList: UserModel[] = []; + isLoading = false; + errorMessage = ''; + + constructor(private readonly usersService: UsersService) {} + + ngOnInit(): void { + this.loadUsers(); + } + + private loadUsers(): void { + this.isLoading = true; + this.usersService.getUsers().subscribe({ + next: (response) => { + this.userList = response; + this.isLoading = false; + }, + error: () => { + this.errorMessage = 'Unable to load users. Please verify backend API availability.'; + this.isLoading = false; + } + }); + } +} diff --git a/src/app/users/model/user.model.ts b/src/app/users/model/user.model.ts new file mode 100644 index 0000000..a14813b --- /dev/null +++ b/src/app/users/model/user.model.ts @@ -0,0 +1,6 @@ +export interface UserModel { + id: number; + firstName: string; + lastName: string; + email: string; +} diff --git a/src/app/users/services/users.service.ts b/src/app/users/services/users.service.ts new file mode 100644 index 0000000..30920c9 --- /dev/null +++ b/src/app/users/services/users.service.ts @@ -0,0 +1,34 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { Observable } from 'rxjs'; + +import { UserModel } from '../model/user.model'; + +const baseUrl = 'http://localhost:8081/api/v1/employees'; + +@Injectable({ + providedIn: 'root' +}) +export class UsersService { + constructor(private readonly http: HttpClient) {} + + getUsers(): Observable { + return this.http.get(baseUrl); + } + + create(data: Partial): Observable { + return this.http.post(baseUrl, data); + } + + update(id: number, data: Partial): Observable { + return this.http.put(`${baseUrl}/${id}`, data); + } + + delete(id: number): Observable { + return this.http.delete(`${baseUrl}/${id}`); + } + + findByEmail(email: string): Observable { + return this.http.get(`${baseUrl}?email=${encodeURIComponent(email)}`); + } +} diff --git a/src/app/users/user-card/user-card.component.css b/src/app/users/user-card/user-card.component.css new file mode 100644 index 0000000..018d755 --- /dev/null +++ b/src/app/users/user-card/user-card.component.css @@ -0,0 +1,3 @@ +.card { + min-height: 180px; +} diff --git a/src/app/users/user-card/user-card.component.html b/src/app/users/user-card/user-card.component.html new file mode 100644 index 0000000..8a9ca91 --- /dev/null +++ b/src/app/users/user-card/user-card.component.html @@ -0,0 +1,8 @@ +
+
USER
+
+
{{ user.firstName }} {{ user.lastName }}
+

{{ user.email }}

+ ID: {{ user.id }} +
+
diff --git a/src/app/users/user-card/user-card.component.spec.ts b/src/app/users/user-card/user-card.component.spec.ts new file mode 100644 index 0000000..c7aea29 --- /dev/null +++ b/src/app/users/user-card/user-card.component.spec.ts @@ -0,0 +1,33 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { UserCardComponent } from './user-card.component'; + +describe('UserCardComponent', () => { + let component: UserCardComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [UserCardComponent] + }).compileComponents(); + + fixture = TestBed.createComponent(UserCardComponent); + component = fixture.componentInstance; + component.user = { + id: 1, + firstName: 'Ada', + lastName: 'Lovelace', + email: 'ada@example.com' + }; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should render user full name', () => { + const compiled = fixture.nativeElement as HTMLElement; + expect(compiled.textContent).toContain('Ada Lovelace'); + }); +}); diff --git a/src/app/users/user-card/user-card.component.ts b/src/app/users/user-card/user-card.component.ts new file mode 100644 index 0000000..bb0cbe9 --- /dev/null +++ b/src/app/users/user-card/user-card.component.ts @@ -0,0 +1,13 @@ +import { Component, Input } from '@angular/core'; + +import { UserModel } from '../model/user.model'; + +@Component({ + selector: 'app-user-card', + standalone: false, + templateUrl: './user-card.component.html', + styleUrls: ['./user-card.component.css'] +}) +export class UserCardComponent { + @Input() user!: UserModel; +} diff --git a/src/app/users/users-routing.module.ts b/src/app/users/users-routing.module.ts new file mode 100644 index 0000000..fb2c450 --- /dev/null +++ b/src/app/users/users-routing.module.ts @@ -0,0 +1,16 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; + +import { CrudComponent } from './crud/crud.component'; + +const routes: Routes = [ + { path: 'all', component: CrudComponent }, + { path: 'create', component: CrudComponent }, + { path: '', redirectTo: 'all', pathMatch: 'full' } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class UsersRoutingModule {} diff --git a/src/app/users/users.module.ts b/src/app/users/users.module.ts new file mode 100644 index 0000000..8d5db8a --- /dev/null +++ b/src/app/users/users.module.ts @@ -0,0 +1,12 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; + +import { UsersRoutingModule } from './users-routing.module'; +import { CrudComponent } from './crud/crud.component'; +import { UserCardComponent } from './user-card/user-card.component'; + +@NgModule({ + declarations: [CrudComponent, UserCardComponent], + imports: [CommonModule, UsersRoutingModule] +}) +export class UsersModule {} diff --git a/src/index.html b/src/index.html new file mode 100644 index 0000000..609cf8a --- /dev/null +++ b/src/index.html @@ -0,0 +1,12 @@ + + + + + Formation Angular + + + + + + + diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..ec6f5c1 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,11 @@ +import 'zone.js'; + +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import { AppModule } from './app/app.module'; + +platformBrowserDynamic() + .bootstrapModule(AppModule) + .catch((err: unknown) => { + console.error(err); + }); diff --git a/src/styles.css b/src/styles.css new file mode 100644 index 0000000..8945d89 --- /dev/null +++ b/src/styles.css @@ -0,0 +1,7 @@ +@import "bootstrap/dist/css/bootstrap.min.css"; + +body { + background-color: #f8f9fa; + margin: 0; + font-family: Arial, Helvetica, sans-serif; +} diff --git a/src/test.ts b/src/test.ts new file mode 100644 index 0000000..724f143 --- /dev/null +++ b/src/test.ts @@ -0,0 +1,13 @@ +import 'zone.js'; +import 'zone.js/testing'; + +import { getTestBed } from '@angular/core/testing'; +import { + BrowserDynamicTestingModule, + platformBrowserDynamicTesting +} from '@angular/platform-browser-dynamic/testing'; + +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()); + +import './app/app.component.spec'; +import './app/users/user-card/user-card.component.spec'; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..418e7eb --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,44 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "baseUrl": "./", + "outDir": "./dist/out-tsc", + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "sourceMap": true, + "declaration": false, + "downlevelIteration": true, + "experimentalDecorators": true, + "moduleResolution": "node", + "importHelpers": true, + "target": "ES2020", + "module": "ES2020", + "lib": [ + "ES2020", + "dom" + ], + "useDefineForClassFields": false, + "skipLibCheck": true + }, + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + }, + "files": [ + "src/main.ts" + ], + "include": [ + "src/**/*.d.ts", + "src/**/*.ts" + ], + "exclude": [ + "src/test.ts", + "src/**/*.spec.ts" + ] +} diff --git a/tsconfig.spec.json b/tsconfig.spec.json new file mode 100644 index 0000000..bd0c796 --- /dev/null +++ b/tsconfig.spec.json @@ -0,0 +1,17 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./out-tsc/spec", + "types": [ + "jasmine" + ] + }, + "files": [ + "src/test.ts" + ], + "include": [ + "src/**/*.spec.ts", + "src/**/*.d.ts" + ], + "exclude": [] +}