add angular material project

This commit is contained in:
liosha84
2025-06-14 19:41:08 +03:00
parent e7eed1e2d2
commit 5d0a701474
84 changed files with 11873 additions and 0 deletions
@@ -0,0 +1,35 @@
<div>
<div class="submit-form">
<div *ngIf="!submitted">
<div class="form-group">
<label for="title">Title</label>
<input
type="text"
class="form-control"
id="title"
required
[(ngModel)]="tutorial.title"
name="title"
/>
</div>
<div class="form-group">
<label for="description">Description</label>
<input
class="form-control"
id="description"
required
[(ngModel)]="tutorial.description"
name="description"
/>
</div>
<button (click)="saveTutorial()" class="btn btn-success">Submit</button>
</div>
<div *ngIf="submitted">
<h4>Tutorial was submitted successfully!</h4>
<button class="btn btn-success" (click)="newTutorial()">Add</button>
</div>
</div>
</div>
@@ -0,0 +1,4 @@
.submit-form {
max-width: 400px;
margin: auto;
}
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AddTutorialComponent } from './add-tutorial.component';
describe('AddTutorialComponent', () => {
let component: AddTutorialComponent;
let fixture: ComponentFixture<AddTutorialComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ AddTutorialComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(AddTutorialComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,51 @@
import { Component, OnInit } from '@angular/core';
import {Tutorial} from '../../models/tutorial.model';
import {TutorialService} from '../../services/tutorial.service';
@Component({
selector: 'app-add-tutorial',
templateUrl: './add-tutorial.component.html',
styleUrls: ['./add-tutorial.component.scss'],
standalone: false
})
export class AddTutorialComponent implements OnInit {
tutorial: Tutorial = {
title: '',
description: '',
published: false
};
submitted = false;
constructor(private tutorialService: TutorialService) { }
ngOnInit(): void {
}
saveTutorial(): void {
const data = {
title: this.tutorial.title,
description: this.tutorial.description
};
this.tutorialService.create(data)
.subscribe(
response => {
console.log(response);
this.submitted = true;
},
error => {
console.log(error);
});
}
newTutorial(): void {
this.submitted = false;
this.tutorial = {
title: '',
description: '',
published: false
};
}
}
@@ -0,0 +1,51 @@
<div class="col-md-6">
<h4>Users List</h4>
<ul class="list-group">
<li
class="list-group-item"
*ngFor="let row of rowData; let i = index"
>
{{ row.username }}
{{ row.email}}
{{ row.password}}
<form>
<mat-form-field class="example-chip-list">
<mat-chip-grid #chipGrid aria-label="Role selection">
@for (role of row.roles; track $index) {
<mat-chip-row (removed)="remove(role)">
{{role.name}}
<button matChipRemove [attr.aria-label]="'remove ' + role.name">
<mat-icon>cancel</mat-icon>
</button>
</mat-chip-row>
}
</mat-chip-grid>
<input
name="currentFruit"
placeholder="Add role..."
#fruitInput
[(ngModel)]="currentRole"
[matChipInputFor]="chipGrid"
[matAutocomplete]="auto"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[formControl]="myControl"
(matChipInputTokenEnd)="add($event)"
(input)="change($event,filteredRoles(row.roles))"
/>
<mat-autocomplete [formControl]="ac" autoActiveFirstOption #auto="matAutocomplete" (optionSelected)="selected(row.roles,$event); ">
@for (role of filteredRoles(row.roles); track role) {
<mat-option [value]="role">{{role.name}}</mat-option>
}
</mat-autocomplete>
</mat-form-field>
</form>
</li>
</ul>
</div>
@@ -0,0 +1,3 @@
.example-chip-list {
width: 100%;
}
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BoardAdminComponent } from './board-admin.component';
describe('BoardAdminComponent', () => {
let component: BoardAdminComponent;
let fixture: ComponentFixture<BoardAdminComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ BoardAdminComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(BoardAdminComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,124 @@
import {Component, computed, model, OnInit} from '@angular/core';
import {User} from "../../models/user.model";
import {MatChipInputEvent} from "@angular/material/chips";
import {MatAutocompleteSelectedEvent} from "@angular/material/autocomplete";
import {COMMA, ENTER} from "@angular/cdk/keycodes";
import {AsyncPipe} from "@angular/common";
import {FormControl} from "@angular/forms";
import {Observable, startWith} from "rxjs";
import {map} from "rxjs/operators";
import {UserService} from '../../services/user.service';
import {RolesService} from '../../services/roles.service';
import {Role} from '../../models/role';
@Component({
selector: 'app-board-admin',
templateUrl: './board-admin.component.html',
styleUrls: ['./board-admin.component.scss'],
standalone: false,
})
export class BoardAdminComponent implements OnInit {
private gridApi: any;
readonly separatorKeysCodes: number[] = [ENTER, COMMA];
rowData?: User[];
allRoles: any;
readonly currentRole = model('');
protected myControl = new FormControl('');
protected ac = new FormControl('');
constructor(private userService: UserService, private roleService: RolesService ) {
this.getAllRoles();
}
ngOnInit(): void {
//this.myControl.valueChanges.pipe(
// startWith(''),
// map(value => this._filter(value || '')),
//);
this.userService.getAdminBoard().subscribe(
(data : any) => {
this.rowData = data;
},
(err : any)=> {
this.rowData = JSON.parse(err.error).message;
}
);
}
filteredRoles(roles : Role[]):any {
return this.allRoles.filter(
(r:Role) => !roles.some((item) => item.id === r.id),
);
}
// private _filter(value: string): string[] {
// const filterValue = value.toLowerCase();
// this.ac.
// return this.options.filter(option => option.toLowerCase().includes(filterValue));
//}
getAllRoles():any{
this.roleService.getAllRoles().subscribe(
(data : any) => {
this.allRoles = data;
},
(err : any)=> {
this.allRoles = JSON.parse(err.error).message;
}
);
}
remove(role: string): void {
// this.fruits.update(fruits => {
// const index = fruits.indexOf(fruit);
// if (index < 0) {
// return fruits;
// }
// fruits.splice(index, 1);
// this.announcer.announce(`Removed ${fruit}`);
// return [...fruits];
}
add(event: MatChipInputEvent): void {
const value = (event.value || '').trim();
// Add our fruit
if (value) {
// this.fruits.update(fruits => [...fruits, value]);
}
// Clear the input value
this.currentRole.set('');
}
selected(roles : Role[], event: MatAutocompleteSelectedEvent): void {
roles.push(event.option.value);
this.currentRole.set('');
event.option.deselect();
}
change($event: Event, roles: Role[]) {
roles.filter(
(r:Role) => !roles.some((item) => item.name?.toLowerCase() === r.id),
)
}
}
@@ -0,0 +1 @@
<p>board-moderator works!</p>
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BoardModeratorComponent } from './board-moderator.component';
describe('BoardModeratorComponent', () => {
let component: BoardModeratorComponent;
let fixture: ComponentFixture<BoardModeratorComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ BoardModeratorComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(BoardModeratorComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,16 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-board-moderator',
templateUrl: './board-moderator.component.html',
styleUrls: ['./board-moderator.component.scss'],
standalone: false
})
export class BoardModeratorComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}
@@ -0,0 +1 @@
<p>board-user works!</p>
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BoardUserComponent } from './board-user.component';
describe('BoardUserComponent', () => {
let component: BoardUserComponent;
let fixture: ComponentFixture<BoardUserComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ BoardUserComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(BoardUserComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,16 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-board-user',
templateUrl: './board-user.component.html',
styleUrls: ['./board-user.component.scss'],
standalone: false
})
export class BoardUserComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}
@@ -0,0 +1,29 @@
<h1 mat-dialog-title>Hi </h1>
<div mat-dialog-content>
<p>User name</p>
<mat-form-field class="fillField">
<input matInput [(ngModel)]="data.username">
</mat-form-field>
<p>Password</p>
<mat-form-field class="fillField">
<mat-label>Enter your password</mat-label>
<input matInput
[type]="hide() ? 'password' : 'text'"
[(ngModel)]="data.password"
/>
<button
mat-icon-button
matSuffix
(click)="clickEvent($event)"
[attr.aria-label]="'Hide password'"
[attr.aria-pressed]="hide()"
>
<mat-icon>{{hide() ? 'visibility_off' : 'visibility'}}</mat-icon>
</button>
</mat-form-field>
</div>
<div mat-dialog-actions>
<button mat-button mat-dialog-close (click)="onNoClick()">No Thanks</button>
<button mat-button [mat-dialog-close]="data" cdkFocusInitial>Ok</button>
</div>
@@ -0,0 +1,4 @@
.fillField{
width: 100%;
};
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { DialogComponent } from './dialog.component';
describe('DialogComponent', () => {
let component: DialogComponent;
let fixture: ComponentFixture<DialogComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [DialogComponent]
})
.compileComponents();
fixture = TestBed.createComponent(DialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,47 @@
import {ChangeDetectionStrategy, Component, Inject, inject, signal} from '@angular/core';
import {MatButtonModule} from "@angular/material/button";
import {
MAT_DIALOG_DATA,
MatDialogActions,
MatDialogClose,
MatDialogContent,
MatDialogRef,
MatDialogTitle
} from "@angular/material/dialog";
import {MatFormField, MatLabel, MatSuffix} from "@angular/material/form-field";
import {MatInput} from "@angular/material/input";
import {FormsModule} from "@angular/forms";
import {MatIcon} from "@angular/material/icon";
import {DialogData} from "../../app.component";
@Component({
selector: 'app-dialog',
imports: [MatButtonModule, MatLabel, MatDialogActions, MatDialogClose, MatDialogTitle, MatDialogContent, MatFormField, MatInput, FormsModule, MatIcon, MatSuffix],
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './dialog.component.html',
styleUrl: './dialog.component.scss'
})
export class DialogComponent {
readonly dialogRef = inject(MatDialogRef<DialogComponent>);
hide = signal(true);
constructor(
@Inject(MAT_DIALOG_DATA) public data:DialogData) {}
onNoClick() {
this.dialogRef.close();
}
clickEvent(event: MouseEvent) {
this.hide.set(!this.hide());
event.stopPropagation();
}
}
@@ -0,0 +1,5 @@
<div class="container">
<header class="jumbotron">
<p>{{ content }}</p>
</header>
</div>
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { HomeComponent } from './home.component';
describe('HomeComponent', () => {
let component: HomeComponent;
let fixture: ComponentFixture<HomeComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ HomeComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(HomeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,26 @@
import { Component, OnInit } from '@angular/core';
import {UserService} from '../../services/user.service';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss'],
standalone: false
})
export class HomeComponent implements OnInit {
content?: string;
constructor(private userService: UserService) { }
ngOnInit(): void {
// this.userService.getPublicContent().subscribe(
// (data : any) => {
// this.content = data;
// },
// (err : any) => {
// this.content = JSON.parse(err.error).message;
// }
// );
}
}
@@ -0,0 +1,75 @@
<div class="col-md-12">
<div class="card card-container">
<img
id="profile-img"
src="//ssl.gstatic.com/accounts/ui/avatar_2x.png"
class="profile-img-card"
/>
<form
*ngIf="!isLoggedIn"
name="form"
(ngSubmit)="f.form.valid && onSubmit()"
#f="ngForm"
novalidate
>
<div class="form-group">
<label for="username">Username</label>
<input
type="text"
class="form-control"
id="username"
[(ngModel)]="form.username"
required
#username="ngModel"
/>
<div
class="alert alert-danger"
role="alert"
*ngIf="username.errors && f.submitted"
>
Username is required!
</div>
</div>
<div class="form-group">
<label for="password">Password</label>
<input
type="password"
class="form-control"
id="password"
[(ngModel)]="form.password"
required
minlength="6"
#password="ngModel"
/>
<div
class="alert alert-danger"
role="alert"
*ngIf="password.errors && f.submitted"
>
<div *ngIf="password.errors['required']">Password is required</div>
<div *ngIf="password.errors['minlength']">
Password must be at least 6 characters
</div>
</div>
</div>
<div class="form-group">
<button class="btn btn-primary btn-block">
Login
</button>
</div>
<div class="form-group">
<div
class="alert alert-danger"
role="alert"
*ngIf="f.submitted && isLoginFailed"
>
Login failed: {{ errorMessage }}
</div>
</div>
</form>
<div class="alert alert-success" *ngIf="isLoggedIn">
Logged in as {{ roles }}.
</div>
</div>
</div>
@@ -0,0 +1 @@
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { LoginComponent } from './login.component';
describe('LoginComponent', () => {
let component: LoginComponent;
let fixture: ComponentFixture<LoginComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ LoginComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,60 @@
import { Component, OnInit } from '@angular/core';
import {FormsModule} from "@angular/forms";
import {NgIf} from "@angular/common";
import {AuthService} from '../../services/auth.service';
import {TokenStorageService} from '../../services/token-storage.service';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
imports: [
FormsModule,
NgIf
],
styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit {
form: any = {
username: null,
password: null
};
isLoggedIn = false;
isLoginFailed = false;
errorMessage = '';
roles: string[] = [];
constructor(private authService: AuthService, private tokenStorage: TokenStorageService) { }
ngOnInit(): void {
if (this.tokenStorage.getToken()) {
this.isLoggedIn = true;
this.roles = this.tokenStorage.getUser().roles;
}
}
onSubmit(): void {
const { username, password } = this.form;
this.authService.login(username, password).subscribe(
data => {
this.tokenStorage.saveToken(data.accessToken);
this.tokenStorage.saveUser(data);
this.isLoginFailed = false;
this.isLoggedIn = true;
this.roles = this.tokenStorage.getUser().roles;
this.reloadPage();
},
err => {
this.errorMessage = err.error.message;
this.isLoginFailed = true;
}
);
}
reloadPage(): void {
window.location.reload();
}
}
@@ -0,0 +1,26 @@
<div class="container" *ngIf="currentUser; else loggedOut">
<header class="jumbotron">
<h3>
<strong>{{ currentUser.username }}</strong> Profile
</h3>
</header>
<p>
<strong>Token:</strong>
{{ currentUser.accessToken.substring(0, 20) }} ...
{{ currentUser.accessToken.substr(currentUser.accessToken.length - 20) }}
</p>
<p>
<strong>Email:</strong>
{{ currentUser.email }}
</p>
<strong>Roles:</strong>
<ul>
<li *ngFor="let role of currentUser.roles">
{{ role }}
</li>
</ul>
</div>
<ng-template #loggedOut>
Please login.
</ng-template>
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ProfileComponent } from './profile.component';
describe('ProfileComponent', () => {
let component: ProfileComponent;
let fixture: ComponentFixture<ProfileComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ ProfileComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ProfileComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,19 @@
import { Component, OnInit } from '@angular/core';
import {TokenStorageService} from '../../services/token-storage.service';
@Component({
selector: 'app-profile',
templateUrl: './profile.component.html',
styleUrls: ['./profile.component.scss'],
standalone: false
})
export class ProfileComponent implements OnInit {
currentUser: any;
constructor(private token: TokenStorageService) { }
ngOnInit(): void {
this.currentUser = this.token.getUser();
}
}
@@ -0,0 +1,89 @@
<div class="col-md-12">
<div id="register">
<img id="foto"
id="profile-img"
src="//ssl.gstatic.com/accounts/ui/avatar_2x.png"
class="profile-img-card"
/>
<form
*ngIf="!isSuccessful"
name="form"
(ngSubmit)="f.form.valid && onSubmit()"
#f="ngForm"
novalidate
>
<div class="form-group">
<label for="username">Username</label>
<input
type="text"
class="form-control"
id="username"
[(ngModel)]="form.username"
[ngModelOptions]="{standalone: true}"
required
minlength="3"
maxlength="20"
#username="ngModel"
/>
<div class="alert-danger" *ngIf="username.errors && f.submitted">
<div *ngIf="username.errors['required']">Username is required</div>
<div *ngIf="username.errors['minlength']">
Username must be at least 3 characters
</div>
<div *ngIf="username.errors['maxlength']">
Username must be at most 20 characters
</div>
</div>
</div>
<div class="form-group">
<label for="email">Email</label>
<input
type="email"
class="form-control"
id="email"
[(ngModel)]="form.email"
[ngModelOptions]="{standalone: true}"
required
email
#email="ngModel"
/>
<div class="alert-danger" *ngIf="email.errors && f.submitted">
<div *ngIf="email.errors['required']">Email is required</div>
<div *ngIf="email.errors['email']">
Email must be a valid email address
</div>
</div>
</div>
<div class="form-group">
<label for="password">Password</label>
<input
type="password"
class="form-control"
id="password"
[(ngModel)]="form.password"
[ngModelOptions]="{standalone: true}"
required
minlength="6"
#password="ngModel"
/>
<div class="alert-danger" *ngIf="password.errors && f.submitted">
<div *ngIf="password.errors['required']">Password is required</div>
<div *ngIf="password.errors['minlength']">
Password must be at least 6 characters
</div>
</div>
</div>
<div class="form-group">
<button class="btn btn-primary btn-block">Sign Up</button>
</div>
<div class="alert alert-warning" *ngIf="f.submitted && isSignUpFailed">
Signup failed!<br />{{ errorMessage }}
</div>
</form>
<div class="alert alert-success" *ngIf="isSuccessful">
Your registration is successful!
</div>
</div>
</div>
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { RegisterComponent } from './register.component';
describe('RegisterComponent', () => {
let component: RegisterComponent;
let fixture: ComponentFixture<RegisterComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ RegisterComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(RegisterComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,41 @@
import { Component, OnInit } from '@angular/core';
import {AuthService} from '../../services/auth.service';
@Component({
selector: 'app-register',
templateUrl: './register.component.html',
styleUrls: ['./register.component.scss'],
standalone: false
})
export class RegisterComponent implements OnInit {
form: any = {
username: null,
email: null,
password: null
};
isSuccessful = false;
isSignUpFailed = false;
errorMessage = '';
constructor(private authService: AuthService) { }
ngOnInit(): void {
}
onSubmit(): void {
const { username, email, password } = this.form;
this.authService.register(username, email, password).subscribe(
data => {
console.log(data);
this.isSuccessful = true;
this.isSignUpFailed = false;
},
err => {
this.errorMessage = err.error.message;
this.isSignUpFailed = true;
}
);
}
}
@@ -0,0 +1,65 @@
<div>
<div *ngIf="currentTutorial.id" class="edit-form">
<h4>Tutorial</h4>
<form>
<div class="form-group">
<label for="title">Title</label>
<input
type="text"
class="form-control"
id="title"
[(ngModel)]="currentTutorial.title"
name="title"
/>
</div>
<div class="form-group">
<label for="description">Description</label>
<input
type="text"
class="form-control"
id="description"
[(ngModel)]="currentTutorial.description"
name="description"
/>
</div>
<div class="form-group">
<label><strong>Status:</strong></label>
{{ currentTutorial.published ? "Published" : "Pending" }}
</div>
</form>
<button
class="badge badge-primary mr-2"
*ngIf="currentTutorial.published"
(click)="updatePublished(false)"
>
UnPublish
</button>
<button
*ngIf="!currentTutorial.published"
class="badge badge-primary mr-2"
(click)="updatePublished(true)"
>
Publish
</button>
<button class="badge badge-danger mr-2" (click)="deleteTutorial()">
Delete
</button>
<button
type="submit"
class="badge badge-success mb-2"
(click)="updateTutorial()"
>
Update
</button>
<p>{{ message }}</p>
</div>
<div *ngIf="!currentTutorial.id">
<br />
<p>Cannot access this Tutorial...</p>
</div>
</div>
@@ -0,0 +1,4 @@
.edit-form {
max-width: 400px;
margin: auto;
}
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TutorialDetailsComponent } from './tutorial-details.component';
describe('TutorialDetailsComponent', () => {
let component: TutorialDetailsComponent;
let fixture: ComponentFixture<TutorialDetailsComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ TutorialDetailsComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(TutorialDetailsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,91 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import {Tutorial} from '../../models/tutorial.model';
import {TutorialService} from '../../services/tutorial.service';
@Component({
selector: 'app-tutorial-details',
templateUrl: './tutorial-details.component.html',
styleUrls: ['./tutorial-details.component.scss'],
standalone: false
})
export class TutorialDetailsComponent implements OnInit {
currentTutorial: Tutorial = {
title: '',
description: '',
published: false
};
message = '';
constructor(
private tutorialService: TutorialService,
private route: ActivatedRoute,
private router: Router) { }
ngOnInit(): void {
this.message = '';
this.getTutorial(this.route.snapshot.params['id']);
}
getTutorial(id: string): void {
this.tutorialService.get(id)
.subscribe(
data => {
this.currentTutorial = data;
console.log(data);
},
error => {
console.log(error);
});
}
updatePublished(status: boolean): void {
const data = {
title: this.currentTutorial.title,
description: this.currentTutorial.description,
published: status
};
this.message = '';
this.tutorialService.update(this.currentTutorial.id, data)
.subscribe(
response => {
this.currentTutorial.published = status;
console.log(response);
this.message = response.message ? response.message : 'The status was updated successfully!';
},
error => {
console.log(error);
});
}
updateTutorial(): void {
this.message = '';
this.tutorialService.update(this.currentTutorial.id, this.currentTutorial)
.subscribe(
response => {
console.log(response);
this.message = response.message ? response.message : 'This tutorial was updated successfully!';
},
error => {
console.log(error);
});
}
deleteTutorial(): void {
this.tutorialService.delete(this.currentTutorial.id)
.subscribe(
response => {
console.log(response);
this.router.navigate(['/tutorials']);
},
error => {
console.log(error);
});
}
}
@@ -0,0 +1,63 @@
<div class="list row">
<div class="col-md-8">
<div class="input-group mb-3">
<input
type="text"
class="form-control"
placeholder="Search by title"
[(ngModel)]="title"
/>
<div class="input-group-append">
<button
class="btn btn-outline-secondary"
type="button"
(click)="searchTitle()"
>
Search
</button>
</div>
</div>
</div>
<div class="col-md-6">
<h4>Tutorials List</h4>
<ul class="list-group">
<li
class="list-group-item"
*ngFor="let tutorial of tutorials; let i = index"
[class.active]="i == currentIndex"
(click)="setActiveTutorial(tutorial, i)"
>
{{ tutorial.title }}
</li>
</ul>
<button class="m-3 btn btn-sm btn-danger" (click)="removeAllTutorials()">
Remove All
</button>
</div>
<div class="col-md-6">
<div *ngIf="currentTutorial.id">
<h4>Tutorial</h4>
<div>
<label><strong>Title:</strong></label> {{ currentTutorial.title }}
</div>
<div>
<label><strong>Description:</strong></label>
{{ currentTutorial.description }}
</div>
<div>
<label><strong>Status:</strong></label>
{{ currentTutorial.published ? "Published" : "Pending" }}
</div>
<a class="badge badge-warning" routerLink="/tutorials/{{ currentTutorial.id }}">
Edit
</a>
</div>
<div *ngIf="!currentTutorial">
<br />
<p>Please click on a Tutorial...</p>
</div>
</div>
</div>
@@ -0,0 +1,5 @@
.list {
text-align: left;
max-width: 750px;
margin: auto;
}
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TutorialsListComponent } from './tutorials-list.component';
describe('TutorialsListComponent', () => {
let component: TutorialsListComponent;
let fixture: ComponentFixture<TutorialsListComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ TutorialsListComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(TutorialsListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,75 @@
import { Component, OnInit } from '@angular/core';
import {Tutorial} from '../../models/tutorial.model';
import {TutorialService} from '../../services/tutorial.service';
@Component({
selector: 'app-tutorials-list',
templateUrl: './tutorials-list.component.html',
styleUrls: ['./tutorials-list.component.scss'],
standalone: false
})
export class TutorialsListComponent implements OnInit {
tutorials?: Tutorial[];
currentTutorial: Tutorial = {};
currentIndex = -1;
title = '';
constructor(private tutorialService: TutorialService) { }
ngOnInit(): void {
this.retrieveTutorials();
}
retrieveTutorials(): void {
this.tutorialService.getAll()
.subscribe(
data => {
this.tutorials = data;
console.log(data);
},
error => {
console.log(error);
});
}
refreshList(): void {
this.retrieveTutorials();
this.currentTutorial = {};
this.currentIndex = -1;
}
setActiveTutorial(tutorial: Tutorial, index: number): void {
this.currentTutorial = tutorial;
this.currentIndex = index;
}
removeAllTutorials(): void {
this.tutorialService.deleteAll()
.subscribe(
response => {
console.log(response);
this.refreshList();
},
error => {
console.log(error);
});
}
searchTitle(): void {
this.currentTutorial = {};
this.currentIndex = -1;
this.tutorialService.findByTitle(this.title)
.subscribe(
data => {
this.tutorials = data;
console.log(data);
},
error => {
console.log(error);
});
}
}