From 027e65a75b945c6b6fb5916108fcbd5dc0a90d96 Mon Sep 17 00:00:00 2001
From: Jones Napoleon Autumn <13518086@std.stei.itb.ac.id>
Date: Tue, 3 Nov 2020 09:03:09 +0700
Subject: [PATCH] final push after copy-pasting and understanding angular app
structure
---
README.md | 32 +-
angular.json | 19 +-
package-lock.json | 25 +
package.json | 2 +
src/app/app-routing.module.ts | 14 +-
src/app/app.component.html | 728 ++++++++++++++----
src/app/app.component.ts | 42 +-
src/app/app.module.ts | 62 +-
.../add-student/add-student.component.css | 0
.../add-student/add-student.component.html | 133 ++++
.../add-student/add-student.component.spec.ts | 25 +
.../add-student/add-student.component.ts | 95 +++
.../edit-student/edit-student.component.css | 0
.../edit-student/edit-student.component.html | 134 ++++
.../edit-student.component.spec.ts | 25 +
.../edit-student/edit-student.component.ts | 114 +++
.../students-list/students-list.component.css | 0
.../students-list.component.html | 64 ++
.../students-list.component.spec.ts | 25 +
.../students-list/students-list.component.ts | 47 ++
src/app/material.module.ts | 59 ++
src/app/shared/api.service.spec.ts | 16 +
src/app/shared/api.service.ts | 69 ++
src/app/shared/student.ts | 9 +
src/index.html | 4 +-
src/styles.css | 149 +++-
26 files changed, 1715 insertions(+), 177 deletions(-)
create mode 100644 src/app/components/add-student/add-student.component.css
create mode 100644 src/app/components/add-student/add-student.component.html
create mode 100644 src/app/components/add-student/add-student.component.spec.ts
create mode 100644 src/app/components/add-student/add-student.component.ts
create mode 100644 src/app/components/edit-student/edit-student.component.css
create mode 100644 src/app/components/edit-student/edit-student.component.html
create mode 100644 src/app/components/edit-student/edit-student.component.spec.ts
create mode 100644 src/app/components/edit-student/edit-student.component.ts
create mode 100644 src/app/components/students-list/students-list.component.css
create mode 100644 src/app/components/students-list/students-list.component.html
create mode 100644 src/app/components/students-list/students-list.component.spec.ts
create mode 100644 src/app/components/students-list/students-list.component.ts
create mode 100644 src/app/material.module.ts
create mode 100644 src/app/shared/api.service.spec.ts
create mode 100644 src/app/shared/api.service.ts
create mode 100644 src/app/shared/student.ts
diff --git a/README.md b/README.md
index 26f409e..66a0662 100644
--- a/README.md
+++ b/README.md
@@ -1,27 +1,21 @@
-# Angular8MeanstackAngularMaterial
+# Tugas kecil 1 jam WBD MEAN STACK tutorial (Frontend)
-This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 10.2.0.
+App untuk student (basic CRUD (juga))
-## Development server
+> Repository ini harus berjalan setelah repository Backend
-Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
+## Prerequisite
-## Code scaffolding
+```
+npm
+```
-Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
+## Install and run
-## Build
+Run `npm install` to install all dependencies
+Run `ng serve` for a dev server.
+Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
-Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.
+## Full Credit
-## Running unit tests
-
-Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
-
-## Running end-to-end tests
-
-Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
-
-## Further help
-
-To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
+https://www.positronx.io/angular-8-mean-stack-tutorial-build-crud-angular-material/
diff --git a/angular.json b/angular.json
index 8b67f98..044af08 100644
--- a/angular.json
+++ b/angular.json
@@ -19,11 +19,9 @@
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": true,
- "assets": [
- "src/favicon.ico",
- "src/assets"
- ],
+ "assets": ["src/favicon.ico", "src/assets"],
"styles": [
+ "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css",
"src/styles.css"
],
"scripts": []
@@ -83,11 +81,9 @@
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
- "assets": [
- "src/favicon.ico",
- "src/assets"
- ],
+ "assets": ["src/favicon.ico", "src/assets"],
"styles": [
+ "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css",
"src/styles.css"
],
"scripts": []
@@ -101,9 +97,7 @@
"tsconfig.spec.json",
"e2e/tsconfig.json"
],
- "exclude": [
- "**/node_modules/**"
- ]
+ "exclude": ["**/node_modules/**"]
}
},
"e2e": {
@@ -119,6 +113,7 @@
}
}
}
- }},
+ }
+ },
"defaultProject": "angular8-meanstack-angular-material"
}
diff --git a/package-lock.json b/package-lock.json
index 0191e4d..e92e219 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -242,6 +242,23 @@
"tslib": "^2.0.0"
}
},
+ "@angular/cdk": {
+ "version": "10.2.7",
+ "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-10.2.7.tgz",
+ "integrity": "sha512-ZQjDfTRTn7JuAKsf3jiIdU2XBaxxGBi/ZWYv5Pb3HCl6B4PISsIE5VWRhkoUogoAB0MiFHpjnWeIqknJEm11YQ==",
+ "requires": {
+ "parse5": "^5.0.0",
+ "tslib": "^2.0.0"
+ },
+ "dependencies": {
+ "parse5": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz",
+ "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==",
+ "optional": true
+ }
+ }
+ },
"@angular/cli": {
"version": "10.2.0",
"resolved": "https://registry.npmjs.org/@angular/cli/-/cli-10.2.0.tgz",
@@ -513,6 +530,14 @@
"tslib": "^2.0.0"
}
},
+ "@angular/material": {
+ "version": "10.2.7",
+ "resolved": "https://registry.npmjs.org/@angular/material/-/material-10.2.7.tgz",
+ "integrity": "sha512-uk6JkRrKHaM9VFMzX7pWC83YNLVgXPB3D8U1yjSOafCdWwrRZgUHGr8MPlSILCr3o2nxgg5SsKdWcWwHuXXUZA==",
+ "requires": {
+ "tslib": "^2.0.0"
+ }
+ },
"@angular/platform-browser": {
"version": "10.2.1",
"resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-10.2.1.tgz",
diff --git a/package.json b/package.json
index 92e4f1a..b590289 100644
--- a/package.json
+++ b/package.json
@@ -12,10 +12,12 @@
"private": true,
"dependencies": {
"@angular/animations": "~10.2.0",
+ "@angular/cdk": "^10.2.7",
"@angular/common": "~10.2.0",
"@angular/compiler": "~10.2.0",
"@angular/core": "~10.2.0",
"@angular/forms": "~10.2.0",
+ "@angular/material": "^10.2.7",
"@angular/platform-browser": "~10.2.0",
"@angular/platform-browser-dynamic": "~10.2.0",
"@angular/router": "~10.2.0",
diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts
index d425c6f..965cd2f 100644
--- a/src/app/app-routing.module.ts
+++ b/src/app/app-routing.module.ts
@@ -1,10 +1,18 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
+import { AddStudentComponent } from './components/add-student/add-student.component';
+import { EditStudentComponent } from './components/edit-student/edit-student.component';
+import { StudentsListComponent } from './components/students-list/students-list.component';
-const routes: Routes = [];
+const routes: Routes = [
+ { path: '', pathMatch: 'full', redirectTo: 'add-student' },
+ { path: 'add-student', component: AddStudentComponent },
+ { path: 'edit-student/:id', component: EditStudentComponent },
+ { path: 'students-list', component: StudentsListComponent },
+];
@NgModule({
imports: [RouterModule.forRoot(routes)],
- exports: [RouterModule]
+ exports: [RouterModule],
})
-export class AppRoutingModule { }
+export class AppRoutingModule {}
diff --git a/src/app/app.component.html b/src/app/app.component.html
index e48d8c1..50ed260 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -1,15 +1,38 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+ add Add Student
+
+
+ format_list_bulleted View Students
+
+
+
+
+
+
+
+
+
-
-
-
-
-
Resources
Here are some links to help you get started:
-
Next Steps
What do you want to do next with your app?
-
+
-
-
+
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
-->
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 3898d24..38e9971 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -1,10 +1,46 @@
-import { Component } from '@angular/core';
+import { Component, ViewChild, HostListener, OnInit } from '@angular/core';
+import { MatSidenav } from '@angular/material/sidenav';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
- styleUrls: ['./app.component.css']
+ styleUrls: ['./app.component.css'],
})
export class AppComponent {
- title = 'angular8-meanstack-angular-material';
+ opened = true;
+ @ViewChild('sidenav') sidenav: MatSidenav;
+
+ ngOnInit() {
+ console.log(window.innerWidth);
+ if (window.innerWidth < 768) {
+ this.sidenav.fixedTopGap = 55;
+ this.opened = false;
+ } else {
+ this.sidenav.fixedTopGap = 55;
+ this.opened = true;
+ }
+ }
+
+ @HostListener('window:resize', ['$event'])
+ onResize(event) {
+ if (event.target.innerWidth < 768) {
+ this.sidenav.fixedTopGap = 55;
+ this.opened = false;
+ } else {
+ this.sidenav.fixedTopGap = 55;
+ this.opened = true;
+ }
+ }
+
+ isBiggerScreen() {
+ const width =
+ window.innerWidth ||
+ document.documentElement.clientWidth ||
+ document.body.clientWidth;
+ if (width < 768) {
+ return true;
+ } else {
+ return false;
+ }
+ }
}
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 2c3ba29..b206efc 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -3,16 +3,68 @@ import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
+import { AddStudentComponent } from './components/add-student/add-student.component';
+import { EditStudentComponent } from './components/edit-student/edit-student.component';
+import { StudentsListComponent } from './components/students-list/students-list.component';
+import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+import { AngularMaterialModule } from './material.module';
+import { ApiService } from './shared/api.service';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { HttpClientModule } from '@angular/common/http';
@NgModule({
declarations: [
- AppComponent
+ AppComponent,
+ AddStudentComponent,
+ EditStudentComponent,
+ StudentsListComponent,
],
imports: [
+ BrowserAnimationsModule,
+ AngularMaterialModule,
+ HttpClientModule,
+ ReactiveFormsModule,
BrowserModule,
- AppRoutingModule
+ AppRoutingModule,
+ FormsModule,
],
- providers: [],
- bootstrap: [AppComponent]
+ providers: [ApiService],
+ bootstrap: [AppComponent],
})
-export class AppModule { }
+export class AppModule {}
+
+// import { BrowserModule } from '@angular/platform-browser';
+// import { NgModule } from '@angular/core';
+
+// import { AppRoutingModule } from './app-routing.module';
+// import { AppComponent } from './app.component';
+// import { AddStudentComponent } from './components/add-student/add-student.component';
+// import { EditStudentComponent } from './components/edit-student/edit-student.component';
+// import { StudentsListComponent } from './components/students-list/students-list.component';
+// import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+
+// @NgModule({
+// declarations: [
+// AppComponent,
+// AddStudentComponent,
+// EditStudentComponent,
+// StudentsListComponent,
+// ],
+// imports: [BrowserModule, AppRoutingModule, BrowserAnimationsModule],
+// providers: [],
+// bootstrap: [AppComponent],
+// })
+// export class AppModule {}
+
+// @NgModule({
+// declarations: [
+// AppComponent,
+// AddStudentComponent,
+// EditStudentComponent,
+// StudentsListComponent,
+// ],
+// imports: [BrowserModule, AppRoutingModule, BrowserAnimationsModule],
+// providers: [],
+// bootstrap: [AppComponent],
+// })
+// export class AppModule {}
diff --git a/src/app/components/add-student/add-student.component.css b/src/app/components/add-student/add-student.component.css
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/components/add-student/add-student.component.html b/src/app/components/add-student/add-student.component.html
new file mode 100644
index 0000000..e9386f8
--- /dev/null
+++ b/src/app/components/add-student/add-student.component.html
@@ -0,0 +1,133 @@
+
+
+
Add Student
+
+
+
+
+
diff --git a/src/app/components/add-student/add-student.component.spec.ts b/src/app/components/add-student/add-student.component.spec.ts
new file mode 100644
index 0000000..08ddca0
--- /dev/null
+++ b/src/app/components/add-student/add-student.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { AddStudentComponent } from './add-student.component';
+
+describe('AddStudentComponent', () => {
+ let component: AddStudentComponent;
+ let fixture: ComponentFixture
;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ AddStudentComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(AddStudentComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/components/add-student/add-student.component.ts b/src/app/components/add-student/add-student.component.ts
new file mode 100644
index 0000000..e505ff0
--- /dev/null
+++ b/src/app/components/add-student/add-student.component.ts
@@ -0,0 +1,95 @@
+import { Router } from '@angular/router';
+import { Component, OnInit, ViewChild, NgZone } from '@angular/core';
+import { COMMA, ENTER } from '@angular/cdk/keycodes';
+import { MatChipInputEvent } from '@angular/material/chips';
+import { ApiService } from './../../shared/api.service';
+import { FormGroup, FormBuilder, Validators } from '@angular/forms';
+
+export interface Subject {
+ name: string;
+}
+
+@Component({
+ selector: 'app-add-student',
+ templateUrl: './add-student.component.html',
+ styleUrls: ['./add-student.component.css'],
+})
+export class AddStudentComponent implements OnInit {
+ visible = true;
+ selectable = true;
+ removable = true;
+ addOnBlur = true;
+ @ViewChild('chipList') chipList;
+ @ViewChild('resetStudentForm') myNgForm;
+ readonly separatorKeysCodes: number[] = [ENTER, COMMA];
+ studentForm: FormGroup;
+ subjectArray: Subject[] = [];
+ SectioinArray: any = ['A', 'B', 'C', 'D', 'E'];
+
+ ngOnInit() {
+ this.submitBookForm();
+ }
+
+ constructor(
+ public fb: FormBuilder,
+ private router: Router,
+ private ngZone: NgZone,
+ private studentApi: ApiService
+ ) {}
+
+ /* Reactive book form */
+ submitBookForm() {
+ this.studentForm = this.fb.group({
+ student_name: ['', [Validators.required]],
+ student_email: ['', [Validators.required]],
+ section: ['', [Validators.required]],
+ subjects: [this.subjectArray],
+ dob: ['', [Validators.required]],
+ gender: ['Male'],
+ });
+ }
+
+ /* Add dynamic languages */
+ add(event: MatChipInputEvent): void {
+ const input = event.input;
+ const value = event.value;
+ // Add language
+ if ((value || '').trim() && this.subjectArray.length < 5) {
+ this.subjectArray.push({ name: value.trim() });
+ }
+ // Reset the input value
+ if (input) {
+ input.value = '';
+ }
+ }
+
+ /* Remove dynamic languages */
+ remove(subject: Subject): void {
+ const index = this.subjectArray.indexOf(subject);
+ if (index >= 0) {
+ this.subjectArray.splice(index, 1);
+ }
+ }
+
+ /* Date */
+ formatDate(e) {
+ var convertDate = new Date(e.target.value).toISOString().substring(0, 10);
+ this.studentForm.get('dob').setValue(convertDate, {
+ onlyself: true,
+ });
+ }
+
+ /* Get errors */
+ public handleError = (controlName: string, errorName: string) => {
+ return this.studentForm.controls[controlName].hasError(errorName);
+ };
+
+ /* Submit book */
+ submitStudentForm() {
+ if (this.studentForm.valid) {
+ this.studentApi.AddStudent(this.studentForm.value).subscribe((res) => {
+ this.ngZone.run(() => this.router.navigateByUrl('/students-list'));
+ });
+ }
+ }
+}
diff --git a/src/app/components/edit-student/edit-student.component.css b/src/app/components/edit-student/edit-student.component.css
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/components/edit-student/edit-student.component.html b/src/app/components/edit-student/edit-student.component.html
new file mode 100644
index 0000000..c836174
--- /dev/null
+++ b/src/app/components/edit-student/edit-student.component.html
@@ -0,0 +1,134 @@
+edit-student works!
+
+
+
Add Student
+
+
+
+
+
diff --git a/src/app/components/edit-student/edit-student.component.spec.ts b/src/app/components/edit-student/edit-student.component.spec.ts
new file mode 100644
index 0000000..3969dd3
--- /dev/null
+++ b/src/app/components/edit-student/edit-student.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { EditStudentComponent } from './edit-student.component';
+
+describe('EditStudentComponent', () => {
+ let component: EditStudentComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ EditStudentComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(EditStudentComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/components/edit-student/edit-student.component.ts b/src/app/components/edit-student/edit-student.component.ts
new file mode 100644
index 0000000..333fccb
--- /dev/null
+++ b/src/app/components/edit-student/edit-student.component.ts
@@ -0,0 +1,114 @@
+import { Router, ActivatedRoute } from '@angular/router';
+import { Component, OnInit, ViewChild, NgZone } from '@angular/core';
+import { COMMA, ENTER } from '@angular/cdk/keycodes';
+import { MatChipInputEvent } from '@angular/material/chips';
+import { ApiService } from './../../shared/api.service';
+import { FormGroup, FormBuilder, Validators } from '@angular/forms';
+
+export interface Subject {
+ name: string;
+}
+
+@Component({
+ selector: 'app-edit-student',
+ templateUrl: './edit-student.component.html',
+ styleUrls: ['./edit-student.component.css'],
+})
+export class EditStudentComponent implements OnInit {
+ visible = true;
+ selectable = true;
+ removable = true;
+ addOnBlur = true;
+ @ViewChild('chipList') chipList;
+ @ViewChild('resetStudentForm') myNgForm;
+ readonly separatorKeysCodes: number[] = [ENTER, COMMA];
+ studentForm: FormGroup;
+ subjectArray: Subject[] = [];
+ SectioinArray: any = ['A', 'B', 'C', 'D', 'E'];
+
+ ngOnInit() {
+ this.updateBookForm();
+ }
+
+ constructor(
+ public fb: FormBuilder,
+ private router: Router,
+ private ngZone: NgZone,
+ private actRoute: ActivatedRoute,
+ private studentApi: ApiService
+ ) {
+ var id = this.actRoute.snapshot.paramMap.get('id');
+ this.studentApi.GetStudent(id).subscribe((data) => {
+ console.log(data.subjects);
+ this.subjectArray = data.subjects;
+ this.studentForm = this.fb.group({
+ student_name: [data.student_name, [Validators.required]],
+ student_email: [data.student_email, [Validators.required]],
+ section: [data.section, [Validators.required]],
+ subjects: [data.subjects],
+ dob: [data.dob, [Validators.required]],
+ gender: [data.gender],
+ });
+ });
+ }
+
+ /* Reactive book form */
+ updateBookForm() {
+ this.studentForm = this.fb.group({
+ student_name: ['', [Validators.required]],
+ student_email: ['', [Validators.required]],
+ section: ['', [Validators.required]],
+ subjects: [this.subjectArray],
+ dob: ['', [Validators.required]],
+ gender: ['Male'],
+ });
+ }
+
+ /* Add dynamic languages */
+ add(event: MatChipInputEvent): void {
+ const input = event.input;
+ const value = event.value;
+ // Add language
+ if ((value || '').trim() && this.subjectArray.length < 5) {
+ this.subjectArray.push({ name: value.trim() });
+ }
+ // Reset the input value
+ if (input) {
+ input.value = '';
+ }
+ }
+
+ /* Remove dynamic languages */
+ remove(subject: Subject): void {
+ const index = this.subjectArray.indexOf(subject);
+ if (index >= 0) {
+ this.subjectArray.splice(index, 1);
+ }
+ }
+
+ /* Date */
+ formatDate(e) {
+ var convertDate = new Date(e.target.value).toISOString().substring(0, 10);
+ this.studentForm.get('dob').setValue(convertDate, {
+ onlyself: true,
+ });
+ }
+
+ /* Get errors */
+ public handleError = (controlName: string, errorName: string) => {
+ return this.studentForm.controls[controlName].hasError(errorName);
+ };
+
+ /* Update book */
+ updateStudentForm() {
+ console.log(this.studentForm.value);
+ var id = this.actRoute.snapshot.paramMap.get('id');
+ if (window.confirm('Are you sure you want to update?')) {
+ this.studentApi
+ .UpdateStudent(id, this.studentForm.value)
+ .subscribe((res) => {
+ this.ngZone.run(() => this.router.navigateByUrl('/students-list'));
+ });
+ }
+ }
+}
diff --git a/src/app/components/students-list/students-list.component.css b/src/app/components/students-list/students-list.component.css
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/components/students-list/students-list.component.html b/src/app/components/students-list/students-list.component.html
new file mode 100644
index 0000000..e6432ec
--- /dev/null
+++ b/src/app/components/students-list/students-list.component.html
@@ -0,0 +1,64 @@
+
+
+
Students List
+
+
+
+
+ There is no student added yet!
+
+
+ 0">
+
+
+
+ Student ID |
+ {{ element._id }} |
+
+
+
+ Student Name |
+ {{ element.student_name }} |
+
+
+
+ Email |
+ {{ element.student_email }} |
+
+
+
+ Section |
+ {{ element.section }} |
+
+
+
+ Action |
+
+
+
+ |
+
+
+
+
+
+
+
+
+
diff --git a/src/app/components/students-list/students-list.component.spec.ts b/src/app/components/students-list/students-list.component.spec.ts
new file mode 100644
index 0000000..bc7d72d
--- /dev/null
+++ b/src/app/components/students-list/students-list.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { StudentsListComponent } from './students-list.component';
+
+describe('StudentsListComponent', () => {
+ let component: StudentsListComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ StudentsListComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(StudentsListComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/components/students-list/students-list.component.ts b/src/app/components/students-list/students-list.component.ts
new file mode 100644
index 0000000..9f69c1d
--- /dev/null
+++ b/src/app/components/students-list/students-list.component.ts
@@ -0,0 +1,47 @@
+import { Student } from './../../shared/student';
+import { ApiService } from './../../shared/api.service';
+import { Component, ViewChild, OnInit } from '@angular/core';
+import { MatPaginator } from '@angular/material/paginator';
+import { MatTableDataSource } from '@angular/material/table';
+
+@Component({
+ selector: 'app-students-list',
+ templateUrl: './students-list.component.html',
+ styleUrls: ['./students-list.component.css'],
+})
+export class StudentsListComponent implements OnInit {
+ StudentData: any = [];
+ dataSource: MatTableDataSource;
+ @ViewChild(MatPaginator) paginator: MatPaginator;
+ displayedColumns: string[] = [
+ '_id',
+ 'student_name',
+ 'student_email',
+ 'section',
+ 'action',
+ ];
+
+ constructor(private studentApi: ApiService) {
+ this.studentApi.GetStudents().subscribe((data) => {
+ this.StudentData = data;
+ this.dataSource = new MatTableDataSource(this.StudentData);
+ setTimeout(() => {
+ this.dataSource.paginator = this.paginator;
+ }, 0);
+ });
+ }
+
+ ngOnInit() {}
+
+ deleteStudent(index: number, e) {
+ if (window.confirm('Are you sure')) {
+ const data = this.dataSource.data;
+ data.splice(
+ this.paginator.pageIndex * this.paginator.pageSize + index,
+ 1
+ );
+ this.dataSource.data = data;
+ this.studentApi.DeleteStudent(e._id).subscribe();
+ }
+ }
+}
diff --git a/src/app/material.module.ts b/src/app/material.module.ts
new file mode 100644
index 0000000..f4c5472
--- /dev/null
+++ b/src/app/material.module.ts
@@ -0,0 +1,59 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+import { MatButtonModule } from '@angular/material/button';
+import { MatToolbarModule } from '@angular/material/toolbar';
+import { MatIconModule } from '@angular/material/icon';
+import { MatListModule } from '@angular/material/list';
+import { MatSidenavModule } from '@angular/material/sidenav';
+import { MatGridListModule } from '@angular/material/grid-list';
+import { MatFormFieldModule } from '@angular/material/form-field';
+
+import { MatInputModule } from '@angular/material/input';
+import { MatSelectModule } from '@angular/material/select';
+import { MatRadioModule } from '@angular/material/radio';
+import { MatDatepickerModule } from '@angular/material/datepicker';
+import { MatChipsModule } from '@angular/material/chips';
+import { MatTooltipModule } from '@angular/material/tooltip';
+import { MatTableModule } from '@angular/material/table';
+import { MatPaginatorModule } from '@angular/material/paginator';
+
+@NgModule({
+ imports: [
+ CommonModule,
+ MatButtonModule,
+ MatToolbarModule,
+ MatIconModule,
+ MatSidenavModule,
+ MatListModule,
+ MatGridListModule,
+ MatFormFieldModule,
+ MatInputModule,
+ MatSelectModule,
+ MatRadioModule,
+ MatDatepickerModule,
+ MatChipsModule,
+ MatTooltipModule,
+ MatTableModule,
+ MatPaginatorModule,
+ ],
+ exports: [
+ MatButtonModule,
+ MatToolbarModule,
+ MatIconModule,
+ MatSidenavModule,
+ MatListModule,
+ MatGridListModule,
+ MatInputModule,
+ MatFormFieldModule,
+ MatSelectModule,
+ MatRadioModule,
+ MatDatepickerModule,
+ MatChipsModule,
+ MatTooltipModule,
+ MatTableModule,
+ MatPaginatorModule,
+ ],
+ providers: [MatDatepickerModule],
+})
+export class AngularMaterialModule {}
diff --git a/src/app/shared/api.service.spec.ts b/src/app/shared/api.service.spec.ts
new file mode 100644
index 0000000..c0310ae
--- /dev/null
+++ b/src/app/shared/api.service.spec.ts
@@ -0,0 +1,16 @@
+import { TestBed } from '@angular/core/testing';
+
+import { ApiService } from './api.service';
+
+describe('ApiService', () => {
+ let service: ApiService;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({});
+ service = TestBed.inject(ApiService);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/src/app/shared/api.service.ts b/src/app/shared/api.service.ts
new file mode 100644
index 0000000..be10231
--- /dev/null
+++ b/src/app/shared/api.service.ts
@@ -0,0 +1,69 @@
+import { Injectable } from '@angular/core';
+import { Student } from './student';
+import { Observable, throwError } from 'rxjs';
+import { catchError, map } from 'rxjs/operators';
+import {
+ HttpClient,
+ HttpHeaders,
+ HttpErrorResponse,
+} from '@angular/common/http';
+
+@Injectable({
+ providedIn: 'root',
+})
+export class ApiService {
+ endpoint: string = 'http://localhost:8000/api';
+ headers = new HttpHeaders().set('Content-Type', 'application/json');
+
+ constructor(private http: HttpClient) {}
+
+ // Add student
+ AddStudent(data: Student): Observable {
+ let API_URL = `${this.endpoint}/add-student`;
+ return this.http.post(API_URL, data).pipe(catchError(this.errorMgmt));
+ }
+
+ // Get all students
+ GetStudents() {
+ return this.http.get(`${this.endpoint}`);
+ }
+
+ // Get student
+ GetStudent(id): Observable {
+ let API_URL = `${this.endpoint}/read-student/${id}`;
+ return this.http.get(API_URL, { headers: this.headers }).pipe(
+ map((res: Response) => {
+ return res || {};
+ }),
+ catchError(this.errorMgmt)
+ );
+ }
+
+ // Update student
+ UpdateStudent(id, data): Observable {
+ let API_URL = `${this.endpoint}/update-student/${id}`;
+ return this.http
+ .put(API_URL, data, { headers: this.headers })
+ .pipe(catchError(this.errorMgmt));
+ }
+
+ // Delete student
+ DeleteStudent(id): Observable {
+ var API_URL = `${this.endpoint}/delete-student/${id}`;
+ return this.http.delete(API_URL).pipe(catchError(this.errorMgmt));
+ }
+
+ // Error handling
+ errorMgmt(error: HttpErrorResponse) {
+ 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}`;
+ }
+ console.log(errorMessage);
+ return throwError(errorMessage);
+ }
+}
diff --git a/src/app/shared/student.ts b/src/app/shared/student.ts
new file mode 100644
index 0000000..8cf6870
--- /dev/null
+++ b/src/app/shared/student.ts
@@ -0,0 +1,9 @@
+export class Student {
+ _id: String;
+ student_name: String;
+ student_email: String;
+ section: String;
+ subjects: Array;
+ dob: Date;
+ gender: String;
+}
diff --git a/src/index.html b/src/index.html
index 400de17..3d992be 100644
--- a/src/index.html
+++ b/src/index.html
@@ -6,8 +6,10 @@
+
+
-
+
diff --git a/src/styles.css b/src/styles.css
index 90d4ee0..14dbd4e 100644
--- a/src/styles.css
+++ b/src/styles.css
@@ -1 +1,148 @@
-/* You can add global styles to this file, and also import other style files */
+html,
+body {
+ height: 100%;
+}
+body {
+ margin: 0;
+ font-family: "Roboto", sans-serif;
+}
+.header {
+ justify-content: space-between;
+}
+.user-profile {
+ margin-left: 15px;
+}
+.mat-sidenav-container {
+ height: 100%;
+ display: flex;
+ flex: 1 1 auto;
+}
+.mat-nav-list .mat-list-item {
+ font-size: 15px;
+}
+.nav-tool-items {
+ display: inline-block;
+ margin-right: 13px;
+}
+.user-profile {
+ margin-left: 15px;
+ cursor: pointer;
+}
+.hamburger {
+ visibility: hidden !important;
+}
+.mat-sidenav,
+.mat-sidenav-content {
+ padding: 15px;
+}
+.mat-list-item.active {
+ background: rgba(0, 0, 0, 0.04);
+}
+.mat-sidenav-content {
+ padding: 25px 40px 0;
+}
+.mat-sidenav {
+ background-color: #f2f2f2;
+ width: 250px;
+}
+.header {
+ position: sticky;
+ position: -webkit-sticky;
+ top: 0;
+ z-index: 1000;
+}
+mat-sidenav mat-icon {
+ margin-right: 12px;
+}
+.hamburger {
+ margin-top: 5px;
+ cursor: pointer;
+}
+.mat-radio-button,
+.mat-radio-group {
+ margin-right: 25px;
+}
+.controlers-wrapper > * {
+ width: 100%;
+ padding: 0;
+}
+.misc-bottom-padding {
+ margin: 8px 0 10px;
+}
+.misc-bottom-padding mat-label {
+ margin-right: 15px;
+}
+mat-radio-group mat-radio-button {
+ margin-left: 5px;
+}
+.button-wrapper button {
+ margin-right: 5px;
+}
+table.mat-table,
+table {
+ width: 100%;
+}
+.inner-wrapper {
+ padding: 15px 0 130px;
+ width: 100%;
+}
+.inner-wrapper mat-card {
+ display: inline-block;
+ margin: 0 6% 0 0;
+ vertical-align: top;
+ width: 44%;
+}
+.full-wrapper {
+ width: 100%;
+}
+.multiple-items {
+ position: relative;
+}
+.multiple-items .tooltip-info {
+ right: 0;
+ top: 7px;
+ cursor: pointer;
+ color: #a1a7c7;
+ position: absolute;
+ font-size: 20px;
+}
+body .push-right {
+ margin-right: 10px;
+}
+.no-data {
+ text-align: center;
+ padding-top: 30px;
+ color: #6c75a9;
+}
+.button-wrapper {
+ margin: 20px 0 0 0;
+}
+@media (max-width: 1024px) {
+ .inner-wrapper mat-card {
+ width: 100%;
+ }
+ .mat-sidenav-content {
+ padding: 20px 20px 0;
+ }
+ .misc-bottom-padding mat-label {
+ display: block;
+ padding-bottom: 10px;
+ }
+ .mat-sidenav {
+ width: 230px;
+ }
+ .mat-nav-list .mat-list-item {
+ font-size: 14px;
+ }
+}
+@media (max-width: 767px) {
+ .nav-tool-items {
+ margin-right: 0;
+ }
+ .hamburger {
+ visibility: visible !important;
+ }
+}
+
+html, body { height: 100%; }
+body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
--
GitLab