313 lines
8.3 KiB
TypeScript
313 lines
8.3 KiB
TypeScript
import { Component, OnInit } from '@angular/core';
|
|
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
|
import { AngularEditorConfig } from '@josipv/angular-editor-k2';
|
|
import { AuthenticationService } from 'src/app/service/authentication.service';
|
|
import { BlogService } from 'src/app/service/blog.service';
|
|
import { ProfessorService } from 'src/app/service/professor.service';
|
|
|
|
@Component({
|
|
selector: 'app-blog',
|
|
templateUrl: './blog.component.html',
|
|
styleUrls: ['./blog.component.css'],
|
|
})
|
|
export class BlogComponent implements OnInit {
|
|
blogs: any[] = [];
|
|
allProfessors: any[] = [];
|
|
selectedBlog: any = null;
|
|
blogForm: FormGroup;
|
|
editing: boolean = false;
|
|
loggedInUser: any;
|
|
currentBlog: any = null;
|
|
isShowForm = false;
|
|
content = '';
|
|
|
|
// Image upload properties
|
|
selectedImage: File | null = null;
|
|
imagePreviewUrl: string | null = null;
|
|
uploadingImage: boolean = false;
|
|
|
|
constructor(
|
|
private blogService: BlogService,
|
|
private authService: AuthenticationService,
|
|
private professorService: ProfessorService,
|
|
private fb: FormBuilder
|
|
) {
|
|
// Initialize form with form controls
|
|
this.blogForm = this.fb.group({
|
|
title: ['', Validators.required],
|
|
content: ['', Validators.required],
|
|
professors: [[], Validators.required],
|
|
tags: ['', Validators.required],
|
|
posted: [true],
|
|
});
|
|
}
|
|
|
|
editorConfig: AngularEditorConfig = {
|
|
editable: true,
|
|
spellcheck: true,
|
|
height: '10',
|
|
minHeight: '0',
|
|
maxHeight: 'auto',
|
|
width: 'auto',
|
|
minWidth: '0',
|
|
translate: 'yes',
|
|
enableToolbar: true,
|
|
showToolbar: true,
|
|
placeholder: 'Enter text here...',
|
|
defaultParagraphSeparator: '',
|
|
defaultFontName: '',
|
|
defaultFontSize: '',
|
|
fonts: [
|
|
{ class: 'arial', name: 'Arial' },
|
|
{ class: 'times-new-roman', name: 'Times New Roman' },
|
|
{ class: 'calibri', name: 'Calibri' },
|
|
{ class: 'comic-sans-ms', name: 'Comic Sans MS' },
|
|
],
|
|
customClasses: [
|
|
{
|
|
name: 'quote',
|
|
class: 'quote',
|
|
},
|
|
{
|
|
name: 'redText',
|
|
class: 'redText',
|
|
},
|
|
{
|
|
name: 'titleText',
|
|
class: 'titleText',
|
|
tag: 'h1',
|
|
},
|
|
],
|
|
sanitize: true,
|
|
toolbarPosition: 'top',
|
|
toolbarHiddenButtons: [['bold', 'italic'], ['fontSize']],
|
|
};
|
|
|
|
ngOnInit(): void {
|
|
this.loggedInUser = this.authService.getUserFromLocalStorage();
|
|
this.professorService
|
|
.getAllProfessors()
|
|
.subscribe((res) => (this.allProfessors = res.content));
|
|
|
|
this.loadBlogs();
|
|
|
|
// Subscribe to form value changes to update content for preview
|
|
this.blogForm.get('content')?.valueChanges.subscribe((value) => {
|
|
this.content = value;
|
|
});
|
|
}
|
|
|
|
showForm() {
|
|
this.isShowForm = true;
|
|
this.resetForm();
|
|
}
|
|
|
|
showTable() {
|
|
this.isShowForm = false;
|
|
this.resetForm();
|
|
}
|
|
|
|
loadBlogs() {
|
|
this.blogService.getBlogs().subscribe(data => {
|
|
this.blogs = data;
|
|
});
|
|
}
|
|
|
|
createBlog() {
|
|
this.showForm();
|
|
this.blogForm.reset();
|
|
this.selectedBlog = null;
|
|
this.editing = false;
|
|
}
|
|
|
|
editBlog(blog: any) {
|
|
this.selectedBlog = blog;
|
|
|
|
this.blogForm.patchValue({
|
|
title: blog.title,
|
|
content: blog.content,
|
|
posted: blog.posted,
|
|
professors: blog.professors.map((prof: any) => prof.id),
|
|
tags: blog.tags.join(', ')
|
|
});
|
|
|
|
// Set image preview if exists
|
|
if (blog.imageUrl) {
|
|
this.imagePreviewUrl = blog.imageUrl;
|
|
}
|
|
|
|
this.editing = true;
|
|
this.isShowForm = true;
|
|
}
|
|
|
|
// Image upload methods
|
|
onImageSelected(event: any) {
|
|
const file = event.target.files[0];
|
|
if (file) {
|
|
// Validate file type
|
|
if (!file.type.startsWith('image/')) {
|
|
alert('Please select a valid image file.');
|
|
return;
|
|
}
|
|
|
|
// Validate file size (10MB max)
|
|
const maxSize = 10 * 1024 * 1024; // 10MB in bytes
|
|
if (file.size > maxSize) {
|
|
alert('File size must be less than 10MB.');
|
|
return;
|
|
}
|
|
|
|
this.selectedImage = file;
|
|
|
|
// Create preview URL
|
|
const reader = new FileReader();
|
|
reader.onload = (e: any) => {
|
|
this.imagePreviewUrl = e.target.result;
|
|
};
|
|
reader.readAsDataURL(file);
|
|
}
|
|
}
|
|
|
|
removeImage() {
|
|
this.selectedImage = null;
|
|
this.imagePreviewUrl = null;
|
|
|
|
// Clear the file input
|
|
const fileInput = document.getElementById('image') as HTMLInputElement;
|
|
if (fileInput) {
|
|
fileInput.value = '';
|
|
}
|
|
}
|
|
|
|
async uploadImage(): Promise<string | null> {
|
|
if (!this.selectedImage) return null;
|
|
|
|
this.uploadingImage = true;
|
|
try {
|
|
const response = await this.blogService.uploadImage(this.selectedImage).toPromise();
|
|
return response.url;
|
|
} catch (error) {
|
|
console.error('Error uploading image:', error);
|
|
alert('Failed to upload image. Please try again.');
|
|
return null;
|
|
} finally {
|
|
this.uploadingImage = false;
|
|
}
|
|
}
|
|
|
|
async saveBlog() {
|
|
if (this.blogForm.valid) {
|
|
let imageUrl = null;
|
|
|
|
// Upload image if selected
|
|
if (this.selectedImage) {
|
|
imageUrl = await this.uploadImage();
|
|
if (!imageUrl) {
|
|
return; // Stop if image upload failed
|
|
}
|
|
}
|
|
|
|
const blogData = this.blogForm.value;
|
|
|
|
// Convert tags to array and professors to array of IDs
|
|
blogData.tags = blogData.tags.split(',').map((tag: string) => tag.trim());
|
|
blogData.professors = blogData.professors || [];
|
|
|
|
// Add image URL if uploaded, or keep existing image for updates
|
|
if (imageUrl) {
|
|
blogData.imageUrl = imageUrl;
|
|
} else if (this.editing && this.selectedBlog && this.selectedBlog.imageUrl && this.imagePreviewUrl) {
|
|
// Keep existing image URL if editing and no new image selected
|
|
blogData.imageUrl = this.selectedBlog.imageUrl;
|
|
}
|
|
|
|
blogData.author = this.loggedInUser._id;
|
|
|
|
if (this.editing && this.selectedBlog) {
|
|
this.blogService.updateBlog(this.selectedBlog.id, blogData).subscribe({
|
|
next: () => {
|
|
this.loadBlogs();
|
|
this.resetForm();
|
|
this.isShowForm = false;
|
|
alert('Blog updated successfully!');
|
|
},
|
|
error: (error) => {
|
|
console.error('Error updating blog:', error);
|
|
alert('Failed to update blog. Please try again.');
|
|
}
|
|
});
|
|
} else {
|
|
this.blogService.createBlog(blogData).subscribe({
|
|
next: () => {
|
|
this.loadBlogs();
|
|
this.resetForm();
|
|
this.isShowForm = false;
|
|
alert('Blog created successfully!');
|
|
},
|
|
error: (error) => {
|
|
console.error('Error creating blog:', error);
|
|
alert('Failed to create blog. Please try again.');
|
|
}
|
|
});
|
|
}
|
|
} else {
|
|
// Mark all fields as touched to show validation errors
|
|
Object.keys(this.blogForm.controls).forEach(key => {
|
|
this.blogForm.get(key)?.markAsTouched();
|
|
});
|
|
alert('Please fill in all required fields.');
|
|
}
|
|
}
|
|
|
|
deleteBlog(blog: any) {
|
|
if (confirm('Are you sure you want to delete this blog?')) {
|
|
this.blogService.deleteBlog(blog.id).subscribe({
|
|
next: () => {
|
|
this.loadBlogs();
|
|
alert('Blog deleted successfully!');
|
|
},
|
|
error: (error) => {
|
|
console.error('Error deleting blog:', error);
|
|
alert('Failed to delete blog. Please try again.');
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
resetForm() {
|
|
this.blogForm.reset();
|
|
this.selectedBlog = null;
|
|
this.editing = false;
|
|
this.selectedImage = null;
|
|
this.imagePreviewUrl = null;
|
|
|
|
this.blogForm.patchValue({
|
|
professors: [],
|
|
tags: '',
|
|
posted: true
|
|
});
|
|
|
|
// Clear the file input
|
|
const fileInput = document.getElementById('image') as HTMLInputElement;
|
|
if (fileInput) {
|
|
fileInput.value = '';
|
|
}
|
|
}
|
|
|
|
// Utility method to check if form field has error
|
|
hasError(fieldName: string): boolean {
|
|
const field = this.blogForm.get(fieldName);
|
|
return !!(field && field.invalid && field.touched);
|
|
}
|
|
|
|
// Utility method to get error message for a field
|
|
getErrorMessage(fieldName: string): string {
|
|
const field = this.blogForm.get(fieldName);
|
|
if (field && field.errors && field.touched) {
|
|
if (field.errors['required']) {
|
|
return `${fieldName} is required.`;
|
|
}
|
|
}
|
|
return '';
|
|
}
|
|
} |