Enhance tutorial management with user-specific features and improve error handling
This commit is contained in:
@@ -28,11 +28,7 @@ export class AuthInterceptor implements HttpInterceptor {
|
||||
if (
|
||||
error instanceof HttpErrorResponse &&
|
||||
!req.url.includes('auth/signin') &&
|
||||
(error.status === 401
|
||||
|| error.status === 500
|
||||
|| error.status === 0
|
||||
|
||||
) /// must be only 401 without 500 and 0
|
||||
(error.status === 401) /// must be only 401 without 500 and 0
|
||||
) {
|
||||
return this.handle401Error(req, next);
|
||||
}
|
||||
|
||||
@@ -141,8 +141,10 @@ export class MainComponent implements OnInit{
|
||||
this.storageService.clean();
|
||||
|
||||
//window.location.reload();
|
||||
this.router.navigate([environment.default_page]);
|
||||
window.location.reload();
|
||||
this.router.navigate([environment.default_page]).then(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
//window.location.reload();
|
||||
},
|
||||
error: err => {
|
||||
console.log(err);
|
||||
@@ -175,7 +177,7 @@ export class MainComponent implements OnInit{
|
||||
this.authService.login(this.dialogLoginData.username, this.dialogLoginData.password).subscribe(
|
||||
data => {
|
||||
|
||||
//this.storageService.saveToken(data.token);
|
||||
|
||||
this.storageService.saveUser(data);
|
||||
|
||||
this.isLoggedIn = true;
|
||||
@@ -191,8 +193,7 @@ export class MainComponent implements OnInit{
|
||||
}
|
||||
);
|
||||
|
||||
// do something here with the data
|
||||
dialogSubmitSubscription.unsubscribe();
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+34
-1
@@ -1 +1,34 @@
|
||||
<p>tutorial-add.component works!</p>
|
||||
<mat-card appearance="outlined">
|
||||
<mat-card-header>
|
||||
<mat-card-title>Add tutorial</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content >
|
||||
<mat-form-field class="example-full-width">
|
||||
<mat-label>Title</mat-label>
|
||||
<input matInput required
|
||||
[(ngModel)]="tutorial.title">
|
||||
</mat-form-field>
|
||||
|
||||
<mat-tab-group>
|
||||
<mat-tab label="Markdown text">
|
||||
<textarea class="variable-textarea" [(ngModel)]="tutorial.description"></textarea>
|
||||
<markdown class="variable-binding" [data]="tutorial.description"></markdown>
|
||||
</mat-tab>
|
||||
<mat-tab label="Result">
|
||||
<markdown class="preview" [data]="tutorial.description"></markdown>
|
||||
</mat-tab>
|
||||
<mat-tab label="Example">
|
||||
<textarea class="variable-textarea" [(ngModel)]="markdown"></textarea>
|
||||
<markdown class="variable-binding" [data]="markdown"></markdown>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
</mat-card-content>
|
||||
<mat-card-actions>
|
||||
<button matButton (click)="saveTutorial()" *ngIf="!submitted">Save</button>
|
||||
<div *ngIf="submitted">
|
||||
<h4>Tutorial was submitted successfully!</h4>
|
||||
<button matButton (click)="newTutorial()">Add new tutorial</button>
|
||||
</div>
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
.submit-form {
|
||||
max-width: 400px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
mat-card{
|
||||
margin: 20px;
|
||||
}
|
||||
mat-card-title{
|
||||
color: cyan;
|
||||
}
|
||||
|
||||
.example-form {
|
||||
min-width: 150px;
|
||||
max-width: 500px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
.example-full-width {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
.variable-binding,
|
||||
.variable-textarea {
|
||||
width: 49%;
|
||||
}
|
||||
|
||||
.variable-textarea {
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,.07);
|
||||
min-height: 420px;
|
||||
padding: 8px;
|
||||
transition: all 300ms ease-out;
|
||||
}
|
||||
|
||||
.variable-textarea:hover {
|
||||
box-shadow: 0 6px 12px 3px rgba(0,0,0,.09),
|
||||
0 2px 3px 1px rgba(0,0,0,.06);
|
||||
}
|
||||
|
||||
.variable-binding {
|
||||
display: block;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.preview {
|
||||
/* display: block;
|
||||
float: right;*/
|
||||
}
|
||||
|
||||
@@ -1,11 +1,91 @@
|
||||
import { Component } from '@angular/core';
|
||||
import {Component, CUSTOM_ELEMENTS_SCHEMA} from '@angular/core';
|
||||
import {UserApiService} from '../user-api.service';
|
||||
import {TokenStorageService} from '../../services/token-storage.service';
|
||||
import {EventBusService} from '../../_shared/event-bus.service';
|
||||
import {Router} from '@angular/router';
|
||||
import {AuthService} from '../../services/auth.service';
|
||||
import {Tutorial} from '../../models/tutorial.model';
|
||||
import {MarkdownComponent} from 'ngx-markdown';
|
||||
import {MatButton} from '@angular/material/button';
|
||||
import {MatCard, MatCardActions, MatCardContent, MatCardHeader} from '@angular/material/card';
|
||||
import {MatFormField, MatInput, MatLabel} from '@angular/material/input';
|
||||
import {MatTab, MatTabGroup} from '@angular/material/tabs';
|
||||
import {NgIf} from '@angular/common';
|
||||
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
|
||||
|
||||
@Component({
|
||||
selector: 'app-tutorial-add.component',
|
||||
imports: [],
|
||||
imports: [
|
||||
MarkdownComponent,
|
||||
MatButton,
|
||||
MatCard,
|
||||
MatCardActions,
|
||||
MatCardContent,
|
||||
MatCardHeader,
|
||||
MatFormField,
|
||||
MatInput,
|
||||
MatLabel,
|
||||
MatTab,
|
||||
MatTabGroup,
|
||||
NgIf,
|
||||
ReactiveFormsModule,
|
||||
FormsModule
|
||||
],
|
||||
templateUrl: './tutorial-add.component.html',
|
||||
styleUrl: './tutorial-add.component.scss'
|
||||
styleUrl: './tutorial-add.component.scss',
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
export class TutorialAddComponent {
|
||||
tutorial: Tutorial = new Tutorial();
|
||||
submitted = false
|
||||
|
||||
markdown = `## Markdown __rulez__!
|
||||
---
|
||||
|
||||
### Syntax highlight
|
||||
\`\`\`typescript
|
||||
const language = 'typescript';
|
||||
\`\`\`
|
||||
|
||||
### Lists
|
||||
1. Ordered list
|
||||
2. Another bullet point
|
||||
- Unordered list
|
||||
- Another unordered bullet
|
||||
|
||||
### Blockquote
|
||||
> Blockquote to the max`;
|
||||
|
||||
|
||||
constructor(private userApiService: UserApiService,
|
||||
private storageService: TokenStorageService,
|
||||
private eventBusService: EventBusService,
|
||||
private router: Router, private authService: AuthService) {
|
||||
|
||||
this.tutorial.description = this.markdown;
|
||||
}
|
||||
saveTutorial(): void {
|
||||
const data = {
|
||||
title: this.tutorial.title,
|
||||
description: this.tutorial.description
|
||||
};
|
||||
|
||||
this.userApiService.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
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -56,8 +56,7 @@ export class TutorialsListComponent implements OnInit {
|
||||
if (
|
||||
(
|
||||
error.status === 401
|
||||
|| error.status === 500
|
||||
|| error.status === 0
|
||||
|
||||
)
|
||||
&& this.storageService.isLoggedIn()
|
||||
) {
|
||||
@@ -77,7 +76,7 @@ export class TutorialsListComponent implements OnInit {
|
||||
|
||||
//window.location.reload();
|
||||
this.router.navigate(['main/generate-image']).then(() => {
|
||||
window.location.reload();
|
||||
//window.location.reload();
|
||||
})
|
||||
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import {Observable} from 'rxjs';
|
||||
import {Tutorial} from '../models/tutorial.model';
|
||||
import {HttpClient} from '@angular/common/http';
|
||||
import {HttpClient, HttpHeaders} from '@angular/common/http';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@@ -9,11 +9,19 @@ import {HttpClient} from '@angular/common/http';
|
||||
export class UserApiService {
|
||||
baseUrl = 'http://localhost:8080/api/user';
|
||||
|
||||
httpOptions = {
|
||||
headers: new HttpHeaders({ 'Content-Type': 'application/json' } )
|
||||
};
|
||||
|
||||
constructor(private http: HttpClient) {
|
||||
|
||||
}
|
||||
|
||||
getUserAllTutorials(): Observable<Tutorial[]> {
|
||||
return this.http.get<Tutorial[]>(`${this.baseUrl}/tutorials`,{withCredentials: true});
|
||||
return this.http.get<Tutorial[]>(`${this.baseUrl}/tutorials`, this.httpOptions);
|
||||
}
|
||||
|
||||
create(data: any): Observable<any> {
|
||||
return this.http.post(`${this.baseUrl}/tutorial-add`, data);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user