diff --git a/README.md b/README.md new file mode 100644 index 0000000..134adfe --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# angular-ivy-pgvvxe + +[Edit on StackBlitz ⚡️](https://stackblitz.com/edit/angular-ivy-pgvvxe) \ No newline at end of file diff --git a/angular.json b/angular.json new file mode 100644 index 0000000..7a03df9 --- /dev/null +++ b/angular.json @@ -0,0 +1,100 @@ +{ + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "newProjectRoot": "projects", + "projects": { + "demo": { + "root": "", + "sourceRoot": "src", + "projectType": "application", + "prefix": "app", + "schematics": {}, + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:browser", + "options": { + "outputPath": "dist/demo", + "index": "src/index.html", + "main": "src/main.ts", + "polyfills": "src/polyfills.ts", + "tsConfig": "src/tsconfig.app.json", + "assets": [ + "src/favicon.ico", + "src/assets" + ], + "styles": [ + "src/styles.css" + ], + "scripts": [] + }, + "configurations": { + "production": { + "fileReplacements": [ + { + "replace": "src/environments/environment.ts", + "with": "src/environments/environment.prod.ts" + } + ], + "optimization": true, + "outputHashing": "all", + "sourceMap": false, + "extractCss": true, + "namedChunks": false, + "aot": true, + "extractLicenses": true, + "vendorChunk": false, + "buildOptimizer": true + } + } + }, + "serve": { + "builder": "@angular-devkit/build-angular:dev-server", + "options": { + "browserTarget": "demo:build" + }, + "configurations": { + "production": { + "browserTarget": "demo:build:production" + } + } + }, + "extract-i18n": { + "builder": "@angular-devkit/build-angular:extract-i18n", + "options": { + "browserTarget": "demo:build" + } + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "main": "src/test.ts", + "polyfills": "src/polyfills.ts", + "tsConfig": "src/tsconfig.spec.json", + "karmaConfig": "src/karma.conf.js", + "styles": [ + "styles.css" + ], + "scripts": [], + "assets": [ + "src/favicon.ico", + "src/assets" + ] + } + }, + "lint": { + "builder": "@angular-devkit/build-angular:tslint", + "options": { + "tsConfig": [ + "src/tsconfig.app.json", + "src/tsconfig.spec.json" + ], + "exclude": [ + "**/node_modules/**" + ] + } + } + } + } + }, + "defaultProject": "demo" +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..5a3b276 --- /dev/null +++ b/package.json @@ -0,0 +1,48 @@ +{ + "name": "angular", + "version": "0.0.0", + "private": true, + "dependencies": { + "@angular/animations": "^13.2.0", + "@angular/common": "^13.2.0", + "@angular/compiler": "^13.2.0", + "@angular/core": "^13.2.0", + "@angular/forms": "^13.2.0", + "@angular/platform-browser": "^13.2.0", + "@angular/platform-browser-dynamic": "^13.2.0", + "@angular/router": "^13.2.0", + "@popperjs/core": "^2.10.2", + "bootstrap": "^5.1.3", + "rxjs": "^7.5.2", + "rxjs/operators": "*", + "tslib": "^2.3.1", + "zone.js": "^0.11.4" + }, + "scripts": { + "ng": "ng", + "start": "ng serve", + "build": "ng build", + "test": "ng test", + "lint": "ng lint", + "e2e": "ng e2e" + }, + "devDependencies": { + "@angular-devkit/build-angular": "~0.1100.4", + "@angular/cli": "~11.0.4", + "@angular/compiler-cli": "~11.0.4", + "@types/jasmine": "~3.6.0", + "@types/node": "^12.11.1", + "codelyzer": "^6.0.0", + "jasmine-core": "~3.6.0", + "jasmine-spec-reporter": "~5.0.0", + "karma": "~5.1.0", + "karma-chrome-launcher": "~3.1.0", + "karma-coverage": "~2.0.3", + "karma-jasmine": "~4.0.0", + "karma-jasmine-html-reporter": "^1.5.0", + "protractor": "~7.0.0", + "ts-node": "~8.3.0", + "tslint": "~6.1.0", + "typescript": "~4.0.2" + } +} \ No newline at end of file diff --git a/src/app/app-routing/app-routing.module.ts b/src/app/app-routing/app-routing.module.ts new file mode 100644 index 0000000..3f3b083 --- /dev/null +++ b/src/app/app-routing/app-routing.module.ts @@ -0,0 +1,21 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { Routes, RouterModule } from '@angular/router'; +import { EmployeeCreateComponent } from '../employee-create/employee-create.component'; +import { EmployeeEditComponent } from '../employee-edit/employee-edit.component'; +import { EmployeeListComponent } from '../employee-list/employee-list.component'; +const routes: Routes = [ + { path: '', pathMatch: 'full', redirectTo: 'create-employee' }, + { path: 'create-employee', component: EmployeeCreateComponent }, + { path: 'employees-list', component: EmployeeListComponent }, + { path: 'employee-edit/:id', component: EmployeeEditComponent }, +]; + +@NgModule({ + imports: [ + CommonModule, RouterModule.forRoot(routes) + ], + exports: [ RouterModule ], + declarations: [] +}) +export class AppRoutingModule { } \ No newline at end of file diff --git a/src/app/app.component.css b/src/app/app.component.css new file mode 100644 index 0000000..b7ef084 --- /dev/null +++ b/src/app/app.component.css @@ -0,0 +1,3 @@ +p { + font-family: Lato; +} \ No newline at end of file diff --git a/src/app/app.component.html b/src/app/app.component.html new file mode 100644 index 0000000..e53e43b --- /dev/null +++ b/src/app/app.component.html @@ -0,0 +1,5 @@ + +

+ Start editing to see some magic happen :) +

+ \ No newline at end of file diff --git a/src/app/app.component.ts b/src/app/app.component.ts new file mode 100644 index 0000000..f9ed12b --- /dev/null +++ b/src/app/app.component.ts @@ -0,0 +1,10 @@ +import { Component, VERSION } from '@angular/core'; + +@Component({ + selector: 'my-app', + templateUrl: './app.component.html', + styleUrls: [ './app.component.css' ] +}) +export class AppComponent { + name = 'Angular ' + VERSION.major; +} diff --git a/src/app/app.module.ts b/src/app/app.module.ts new file mode 100644 index 0000000..e2357f9 --- /dev/null +++ b/src/app/app.module.ts @@ -0,0 +1,20 @@ +import { NgModule } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { HttpClientModule } from '@angular/common/http'; +import { AppRoutingModule } from './app-routing/app-routing.module'; + +import { AppComponent } from './app.component'; +import { HelloComponent } from './hello.component'; +import { EmployeeCreateComponent } from './employee-create/employee-create.component'; +import { EmployeeListComponent } from './employee-list/employee-list.component'; +import { EmployeeEditComponent } from './employee-edit/employee-edit.component'; + +@NgModule({ + imports: [ BrowserModule, FormsModule, ReactiveFormsModule, HttpClientModule, AppRoutingModule ], + exports: [], + declarations: [ AppComponent, HelloComponent, EmployeeEditComponent, EmployeeListComponent, EmployeeCreateComponent ], + providers: [], + bootstrap: [ AppComponent ] +}) +export class AppModule { } diff --git a/src/app/employee-create/employee-create.component.css b/src/app/employee-create/employee-create.component.css new file mode 100644 index 0000000..e69de29 diff --git a/src/app/employee-create/employee-create.component.html b/src/app/employee-create/employee-create.component.html new file mode 100644 index 0000000..d53a451 --- /dev/null +++ b/src/app/employee-create/employee-create.component.html @@ -0,0 +1,20 @@ +
+
+

Create Employee

+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
\ No newline at end of file diff --git a/src/app/employee-create/employee-create.component.ts b/src/app/employee-create/employee-create.component.ts new file mode 100644 index 0000000..538a324 --- /dev/null +++ b/src/app/employee-create/employee-create.component.ts @@ -0,0 +1,18 @@ +import { Component, OnInit, Input } from '@angular/core'; +import { Router } from '@angular/router'; +import { RestApiService } from '../shared/rest-api.service'; +@Component({ + selector: 'app-employee-create', + templateUrl: './employee-create.component.html', + styleUrls: ['./employee-create.component.css'], +}) +export class EmployeeCreateComponent implements OnInit { + @Input() employeeDetails = { firstname: '', lastname: '', email: '', phone: '' }; + constructor(public restApi: RestApiService, public router: Router) {} + ngOnInit() {} + addEmployee(dataEmployee: any) { + this.restApi.createEmployee(this.employeeDetails).subscribe((data: {}) => { + this.router.navigate(['/employees-list']); + }); + } +} \ No newline at end of file diff --git a/src/app/employee-edit/employee-edit.component.css b/src/app/employee-edit/employee-edit.component.css new file mode 100644 index 0000000..e69de29 diff --git a/src/app/employee-edit/employee-edit.component.html b/src/app/employee-edit/employee-edit.component.html new file mode 100644 index 0000000..9a3f540 --- /dev/null +++ b/src/app/employee-edit/employee-edit.component.html @@ -0,0 +1,19 @@ +
+
+ +

Update Employee

+
+ +
+
+ +
+
+ +
+
+ +
+ +
+
\ No newline at end of file diff --git a/src/app/employee-edit/employee-edit.component.ts b/src/app/employee-edit/employee-edit.component.ts new file mode 100644 index 0000000..f9ab018 --- /dev/null +++ b/src/app/employee-edit/employee-edit.component.ts @@ -0,0 +1,31 @@ +import { Component, OnInit } from '@angular/core'; +import { RestApiService } from "../shared/rest-api.service"; +import { ActivatedRoute, Router } from '@angular/router'; +@Component({ + selector: 'app-employee-details', + templateUrl: './employee-edit.component.html', + styleUrls: ['./employee-edit.component.scss'] +}) +export class EmployeeEditComponent implements OnInit { + id = this.actRoute.snapshot.params['id']; + employeeData: any = {}; + constructor( + public restApi: RestApiService, + public actRoute: ActivatedRoute, + public router: Router + ) { + } + ngOnInit() { + this.restApi.getEmployee(this.id).subscribe((data: {}) => { + this.employeeData = data; + }) + } + // Update employee data + updateEmployee() { + if(window.confirm('Are you sure, you want to update?')){ + this.restApi.updateEmployee(this.id, this.employeeData).subscribe(data => { + this.router.navigate(['/employees-list']) + }) + } + } +} \ No newline at end of file diff --git a/src/app/employee-list/employee-list.component.css b/src/app/employee-list/employee-list.component.css new file mode 100644 index 0000000..e69de29 diff --git a/src/app/employee-list/employee-list.component.html b/src/app/employee-list/employee-list.component.html new file mode 100644 index 0000000..0a154c9 --- /dev/null +++ b/src/app/employee-list/employee-list.component.html @@ -0,0 +1,41 @@ +
+ +
+

There is no employee added yet!

+ +
+ +
+

Employees List

+
+ + + + + + + + + + + + + + + + + + + +
User IdNameEmailPhoneAction
{{ employee.id }}{{ employee.name }}{{ employee.email }}{{ employee.phone }} + Edit + Delete +
+
+
+
\ No newline at end of file diff --git a/src/app/employee-list/employee-list.component.ts b/src/app/employee-list/employee-list.component.ts new file mode 100644 index 0000000..8953e13 --- /dev/null +++ b/src/app/employee-list/employee-list.component.ts @@ -0,0 +1,28 @@ +import { Component, OnInit } from '@angular/core'; +import { RestApiService } from '../shared/rest-api.service'; +@Component({ + selector: 'app-employee-list', + templateUrl: './employee-list.component.html', + styleUrls: ['./employee-list.component.scss'], +}) +export class EmployeeListComponent implements OnInit { + Employee: any = []; + constructor(public restApi: RestApiService) {} + ngOnInit() { + this.loadEmployees(); + } + // Get employees list + loadEmployees() { + return this.restApi.getEmployees().subscribe((data: {}) => { + this.Employee = data; + }); + } + // Delete employee + deleteEmployee(id: any) { + if (window.confirm('Are you sure, you want to delete?')) { + this.restApi.deleteEmployee(id).subscribe((data) => { + this.loadEmployees(); + }); + } + } +} \ No newline at end of file diff --git a/src/app/hello.component.ts b/src/app/hello.component.ts new file mode 100644 index 0000000..bbc9aa9 --- /dev/null +++ b/src/app/hello.component.ts @@ -0,0 +1,10 @@ +import { Component, Input } from '@angular/core'; + +@Component({ + selector: 'hello', + template: `

Hello {{name}}!

`, + styles: [`h1 { font-family: Lato; }`] +}) +export class HelloComponent { + @Input() name: string; +} diff --git a/src/app/shared/employee.ts b/src/app/shared/employee.ts new file mode 100644 index 0000000..6df1a77 --- /dev/null +++ b/src/app/shared/employee.ts @@ -0,0 +1,7 @@ +export class Employee { + id: string; + firstname: string; + lastname: string; + email: string; + phone: number; +} \ No newline at end of file diff --git a/src/app/shared/rest-api.service.ts b/src/app/shared/rest-api.service.ts new file mode 100644 index 0000000..ee6bac4 --- /dev/null +++ b/src/app/shared/rest-api.service.ts @@ -0,0 +1,76 @@ +import { Injectable } from '@angular/core'; +import { HttpClient, HttpHeaders } from '@angular/common/http'; +import { Employee } from '../shared/employee'; +import { Observable, throwError } from 'rxjs'; +import { retry, catchError } from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root', +}) +export class RestApiService { + // Define API + apiURL = 'http://localhost:3000'; + constructor(private http: HttpClient) {} + /*======================================== + CRUD Methods for consuming RESTful API + =========================================*/ + // Http Options + httpOptions = { + headers: new HttpHeaders({ + 'Content-Type': 'application/json', + }), + }; + // HttpClient API get() method => Fetch employees list + getEmployees(): Observable { + return this.http + .get(this.apiURL + '/employees') + .pipe(retry(1), catchError(this.handleError)); + } + // HttpClient API get() method => Fetch employee + getEmployee(id: any): Observable { + return this.http + .get(this.apiURL + '/employees/' + id) + .pipe(retry(1), catchError(this.handleError)); + } + // HttpClient API post() method => Create employee + createEmployee(employee: any): Observable { + return this.http + .post( + this.apiURL + '/employees', + JSON.stringify(employee), + this.httpOptions + ) + .pipe(retry(1), catchError(this.handleError)); + } + // HttpClient API put() method => Update employee + updateEmployee(id: any, employee: any): Observable { + return this.http + .put( + this.apiURL + '/employees/' + id, + JSON.stringify(employee), + this.httpOptions + ) + .pipe(retry(1), catchError(this.handleError)); + } + // HttpClient API delete() method => Delete employee + deleteEmployee(id: any) { + return this.http + .delete(this.apiURL + '/employees/' + id, this.httpOptions) + .pipe(retry(1), catchError(this.handleError)); + } + // Error handling + handleError(error: any) { + let errorMessage = ''; + if (error.error instanceof ErrorEvent) { + // Get client-side error + errorMessage = error.error.message; + } else { + // Get server-side error + errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`; + } + window.alert(errorMessage); + return throwError(() => { + return errorMessage; + }); + } +} \ No newline at end of file diff --git a/src/index.html b/src/index.html new file mode 100644 index 0000000..f69aaa1 --- /dev/null +++ b/src/index.html @@ -0,0 +1 @@ +loading \ No newline at end of file diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..955a7fb --- /dev/null +++ b/src/main.ts @@ -0,0 +1,16 @@ +import './polyfills'; + +import { enableProdMode } from '@angular/core'; +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import { AppModule } from './app/app.module'; + +platformBrowserDynamic().bootstrapModule(AppModule).then(ref => { + // Ensure Angular destroys itself on hot reloads. + if (window['ngRef']) { + window['ngRef'].destroy(); + } + window['ngRef'] = ref; + + // Otherwise, log the boot error +}).catch(err => console.error(err)); \ No newline at end of file diff --git a/src/polyfills.ts b/src/polyfills.ts new file mode 100644 index 0000000..9c15394 --- /dev/null +++ b/src/polyfills.ts @@ -0,0 +1,71 @@ +/** + * This file includes polyfills needed by Angular and is loaded before the app. + * You can add your own extra polyfills to this file. + * + * This file is divided into 2 sections: + * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. + * 2. Application imports. Files imported after ZoneJS that should be loaded before your main + * file. + * + * The current setup is for so-called "evergreen" browsers; the last versions of browsers that + * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), + * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. + * + * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html + */ + +/*************************************************************************************************** + * BROWSER POLYFILLS + */ + +/** IE9, IE10 and IE11 requires all of the following polyfills. **/ +// import 'core-js/es6/symbol'; +// import 'core-js/es6/object'; +// import 'core-js/es6/function'; +// import 'core-js/es6/parse-int'; +// import 'core-js/es6/parse-float'; +// import 'core-js/es6/number'; +// import 'core-js/es6/math'; +// import 'core-js/es6/string'; +// import 'core-js/es6/date'; +// import 'core-js/es6/array'; +// import 'core-js/es6/regexp'; +// import 'core-js/es6/map'; +// import 'core-js/es6/set'; + +/** IE10 and IE11 requires the following for NgClass support on SVG elements */ +// import 'classlist.js'; // Run `npm install --save classlist.js`. + +/** IE10 and IE11 requires the following to support `@angular/animation`. */ +// import 'web-animations-js'; // Run `npm install --save web-animations-js`. + + +/** Evergreen browsers require these. **/ +// import 'core-js/es6/reflect'; +// import 'core-js/es7/reflect'; + + +/** + * Web Animations `@angular/platform-browser/animations` + * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. + * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). + */ +// import 'web-animations-js'; // Run `npm install --save web-animations-js`. + + + +/*************************************************************************************************** + * Zone JS is required by Angular itself. + */ +import 'zone.js/dist/zone'; // Included with Angular CLI. + + +/*************************************************************************************************** + * APPLICATION IMPORTS + */ + +/** + * Date, currency, decimal and percent pipes. + * Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10 + */ +// import 'intl'; // Run `npm install --save intl`. \ No newline at end of file diff --git a/src/styles.css b/src/styles.css new file mode 100644 index 0000000..74f71b0 --- /dev/null +++ b/src/styles.css @@ -0,0 +1 @@ +/* Add application styles & imports to this file! */ \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..f3c4868 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "baseUrl": "./", + "outDir": "./dist/out-tsc", + "sourceMap": true, + "declaration": false, + "downlevelIteration": true, + "experimentalDecorators": true, + "module": "esnext", + "moduleResolution": "node", + "importHelpers": true, + "target": "es2015", + "typeRoots": [ + "node_modules/@types" + ], + "lib": [ + "es2018", + "dom" + ] + }, + "angularCompilerOptions": { + "enableIvy": true, + "fullTemplateTypeCheck": true, + "strictInjectionParameters": true + } +} \ No newline at end of file