Further updates on 03-11-2025
This commit is contained in:
@@ -1,151 +1,252 @@
|
||||
<app-menu></app-menu>
|
||||
<div class="container mt-4">
|
||||
<div class="d-flex justify-content-between mb-3">
|
||||
<!-- Button to Toggle to Blog Form -->
|
||||
<button *ngIf="!isShowForm" class="btn btn-primary" (click)="showForm()">New Blog</button>
|
||||
<!-- Button to Toggle to Blog List -->
|
||||
<button *ngIf="isShowForm" class="btn btn-secondary" (click)="showTable()">Back to List</button>
|
||||
<div class="blog-layout">
|
||||
<!-- Sidebar -->
|
||||
<app-menu class="sidebar"></app-menu>
|
||||
|
||||
<!-- Main Content -->
|
||||
<div class="blog-content">
|
||||
<!-- Header Section -->
|
||||
<div class="blog-header">
|
||||
<div class="header-left">
|
||||
<h1 class="page-title">Blog Management</h1>
|
||||
<p class="page-subtitle">Create and manage your blog posts</p>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<button *ngIf="!isShowForm" class="btn-primary" (click)="showForm()">
|
||||
<i class="fa fa-plus"></i>
|
||||
<span>New Blog</span>
|
||||
</button>
|
||||
<button *ngIf="isShowForm" class="btn-secondary" (click)="showTable()">
|
||||
<i class="fa fa-arrow-left"></i>
|
||||
<span>Back to List</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Blog Form -->
|
||||
<div *ngIf="isShowForm" class="mb-4">
|
||||
<form [formGroup]="blogForm" (ngSubmit)="saveBlog()">
|
||||
<div class="container">
|
||||
<button type="submit" class="btn btn-primary mx-2">{{ editing ? 'Update Blog' : 'Create Blog'
|
||||
}}</button>
|
||||
<button type="button" class="btn btn-secondary ml-2" (click)="resetForm()">Cancel</button>
|
||||
</div>
|
||||
|
||||
<div class="form-group m-2 ">
|
||||
<label class="text-primary" for="title">Title</label>
|
||||
<input type="text" id="title" class="form-control" formControlName="title"
|
||||
placeholder="Enter blog title">
|
||||
<div *ngIf="blogForm?.get('title')?.invalid && blogForm.get('title')?.touched" class="text-danger">
|
||||
Title is required.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group m-2">
|
||||
<label class="text-primary" for="professors">Professors</label>
|
||||
<select id="professors" formControlName="professors" class="form-control" multiple>
|
||||
<option *ngFor="let professor of allProfessors" [value]="professor.id">
|
||||
{{ professor.firstName }}
|
||||
</option>
|
||||
</select>
|
||||
<div *ngIf="blogForm.get('professors')?.invalid && blogForm.get('professors')?.touched"
|
||||
class="text-danger mt-1">
|
||||
At least one professor must be selected.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group m-2">
|
||||
<label class="text-primary" for="tags">Tags</label>
|
||||
<input type="text" id="tags" class="form-control" formControlName="tags"
|
||||
placeholder="Enter tags separated by commas">
|
||||
<div *ngIf="blogForm.get('tags')?.invalid && blogForm.get('tags')?.touched" class="text-danger mt-1">
|
||||
Tags are required.
|
||||
</div>
|
||||
</div>
|
||||
<!-- Add this section after the tags field and before the posted checkbox -->
|
||||
<div class="form-group m-2">
|
||||
<label class="text-primary" for="image">Blog Image</label>
|
||||
<input type="file" id="image" class="form-control" accept="image/*" (change)="onImageSelected($event)">
|
||||
|
||||
<!-- Image Preview -->
|
||||
<div *ngIf="imagePreviewUrl" class="mt-3">
|
||||
<img [src]="imagePreviewUrl" alt="Image preview" class="img-thumbnail"
|
||||
style="max-width: 300px; max-height: 200px;">
|
||||
<button type="button" class="btn btn-sm btn-danger ml-2"
|
||||
(click)="imagePreviewUrl = null; selectedImage = null;">
|
||||
Remove Image
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Upload Progress -->
|
||||
<div *ngIf="uploadingImage" class="mt-2">
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-striped progress-bar-animated" style="width: 100%">
|
||||
Uploading...
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group m-2">
|
||||
<input type="checkbox" class="mx-2" id="posted" formControlName="posted">
|
||||
<label class="text-primary" for="posted">Posted</label>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="form-group m-2">
|
||||
<label class="text-primary m-1" for="content">Content</label>
|
||||
<angular-editor [config]="editorConfig" [placeholder]="'Enter text here...'"
|
||||
formControlName="content"></angular-editor>
|
||||
<div *ngIf="blogForm.get('content')?.invalid && blogForm.get('content')?.touched"
|
||||
class="text-danger mt-1">
|
||||
Content is required.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="result-container mt-4">
|
||||
<h4 class="text-primary">Preview</h4>
|
||||
<div [innerHTML]="blogForm.get('content')?.value || ''"></div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Blog List -->
|
||||
<div *ngIf="!isShowForm">
|
||||
<div *ngIf="blogs.length > 0">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Title</th>
|
||||
<!-- <th>Content</th> -->
|
||||
<th>Authors</th>
|
||||
<th>Tags</th>
|
||||
<th>Posted</th> <!-- New column for posted status -->
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let blog of blogs">
|
||||
<td>{{ blog.title }}</td>
|
||||
<!-- <td>{{ blog.content | slice:0:50 }}...</td> -->
|
||||
<td>
|
||||
<span *ngFor="let professor of blog.professors">{{ professor.firstName }}<br></span>
|
||||
</td>
|
||||
<td>
|
||||
<span *ngFor="let tag of blog.tags">{{ tag }}<br></span>
|
||||
</td>
|
||||
<td>
|
||||
<span *ngIf="blog.posted" class="text-success">✓</span>
|
||||
<!-- Check mark for posted -->
|
||||
<span *ngIf="!blog.posted" class="text-danger">✗</span>
|
||||
<!-- Cross mark for not posted -->
|
||||
</td>
|
||||
<td>
|
||||
<button class="btn btn-info btn-sm mr-2" (click)="editBlog(blog)">
|
||||
<!-- Added margin-right for spacing -->
|
||||
Edit
|
||||
</button>
|
||||
<button class="btn btn-danger btn-sm" (click)="deleteBlog(blog)">
|
||||
Delete
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Blog Form Section -->
|
||||
<div *ngIf="isShowForm" class="form-container">
|
||||
<form [formGroup]="blogForm" (ngSubmit)="saveBlog()">
|
||||
<!-- Form Actions -->
|
||||
<div class="form-actions-top">
|
||||
<button type="submit" class="btn-primary">
|
||||
<i class="fa fa-save"></i>
|
||||
<span>{{ editing ? 'Update Blog' : 'Create Blog' }}</span>
|
||||
</button>
|
||||
<button type="button" class="btn-cancel" (click)="resetForm()">
|
||||
<i class="fa fa-times"></i>
|
||||
<span>Cancel</span>
|
||||
</button>
|
||||
</div>
|
||||
<div *ngIf="blogs.length === 0" class="alert alert-info">
|
||||
No blogs available. Please create a new blog.
|
||||
|
||||
<!-- Form Card -->
|
||||
<div class="form-card">
|
||||
<!-- Title Field -->
|
||||
<div class="form-group">
|
||||
<label for="title">
|
||||
<i class="fa fa-heading"></i>
|
||||
Blog Title
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="title"
|
||||
class="form-input"
|
||||
formControlName="title"
|
||||
placeholder="Enter a compelling title for your blog post">
|
||||
<div *ngIf="blogForm?.get('title')?.invalid && blogForm.get('title')?.touched" class="error-message">
|
||||
<i class="fa fa-exclamation-circle"></i>
|
||||
Title is required.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Professors Field -->
|
||||
<div class="form-group">
|
||||
<label for="professors">
|
||||
<i class="fa fa-user-tie"></i>
|
||||
Authors (Professors)
|
||||
</label>
|
||||
<select id="professors" formControlName="professors" class="form-select" multiple>
|
||||
<option *ngFor="let professor of allProfessors" [value]="professor.id">
|
||||
{{ professor.firstName }}
|
||||
</option>
|
||||
</select>
|
||||
<small class="form-hint">Hold Ctrl (Windows) or Cmd (Mac) to select multiple authors</small>
|
||||
<div *ngIf="blogForm.get('professors')?.invalid && blogForm.get('professors')?.touched" class="error-message">
|
||||
<i class="fa fa-exclamation-circle"></i>
|
||||
At least one professor must be selected.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tags Field -->
|
||||
<div class="form-group">
|
||||
<label for="tags">
|
||||
<i class="fa fa-tags"></i>
|
||||
Tags
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="tags"
|
||||
class="form-input"
|
||||
formControlName="tags"
|
||||
placeholder="Enter tags separated by commas (e.g., technology, education, innovation)">
|
||||
<small class="form-hint">Separate multiple tags with commas</small>
|
||||
<div *ngIf="blogForm.get('tags')?.invalid && blogForm.get('tags')?.touched" class="error-message">
|
||||
<i class="fa fa-exclamation-circle"></i>
|
||||
Tags are required.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Image Upload Field -->
|
||||
<div class="form-group">
|
||||
<label for="image">
|
||||
<i class="fa fa-image"></i>
|
||||
Blog Image
|
||||
</label>
|
||||
<div class="image-upload-wrapper">
|
||||
<input
|
||||
type="file"
|
||||
id="image"
|
||||
class="file-input"
|
||||
accept="image/*"
|
||||
(change)="onImageSelected($event)">
|
||||
<label for="image" class="file-label">
|
||||
<i class="fa fa-cloud-upload-alt"></i>
|
||||
<span>Choose an image or drag here</span>
|
||||
<small>Supports: JPG, PNG, GIF (Max 10MB)</small>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Image Preview -->
|
||||
<div *ngIf="imagePreviewUrl" class="image-preview-container">
|
||||
<div class="image-preview-wrapper">
|
||||
<img [src]="imagePreviewUrl" alt="Image preview" class="image-preview">
|
||||
<button type="button" class="btn-remove-image" (click)="removeImage()">
|
||||
<i class="fa fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Upload Progress -->
|
||||
<div *ngIf="uploadingImage" class="upload-progress">
|
||||
<div class="progress-bar">
|
||||
<div class="progress-fill"></div>
|
||||
</div>
|
||||
<span class="progress-text">Uploading image...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Posted Checkbox -->
|
||||
<div class="form-group">
|
||||
<div class="checkbox-wrapper">
|
||||
<input type="checkbox" id="posted" formControlName="posted" class="checkbox-input">
|
||||
<label for="posted" class="checkbox-label">
|
||||
<span class="checkbox-custom"></span>
|
||||
<span class="checkbox-text">
|
||||
<i class="fa fa-globe"></i>
|
||||
Publish this blog post
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<small class="form-hint">Check this to make the blog visible to the public</small>
|
||||
</div>
|
||||
|
||||
<!-- Content Editor -->
|
||||
<div class="form-group">
|
||||
<label for="content">
|
||||
<i class="fa fa-pen"></i>
|
||||
Blog Content
|
||||
</label>
|
||||
<div class="editor-wrapper">
|
||||
<angular-editor
|
||||
[config]="editorConfig"
|
||||
[placeholder]="'Write your blog content here...'"
|
||||
formControlName="content">
|
||||
</angular-editor>
|
||||
</div>
|
||||
<div *ngIf="blogForm.get('content')?.invalid && blogForm.get('content')?.touched" class="error-message">
|
||||
<i class="fa fa-exclamation-circle"></i>
|
||||
Content is required.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Preview Card -->
|
||||
<div class="preview-card">
|
||||
<div class="preview-header">
|
||||
<i class="fa fa-eye"></i>
|
||||
<h3>Content Preview</h3>
|
||||
</div>
|
||||
<div class="preview-content" [innerHTML]="blogForm.get('content')?.value || '<p class=\'empty-preview\'>Start writing to see your content preview here...</p>'"></div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Blog List Section -->
|
||||
<div *ngIf="!isShowForm" class="list-container">
|
||||
<div *ngIf="blogs.length > 0" class="table-wrapper">
|
||||
<table class="blog-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Title</th>
|
||||
<th>Authors</th>
|
||||
<th>Tags</th>
|
||||
<th>Status</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let blog of blogs">
|
||||
<td>
|
||||
<div class="blog-title-cell">
|
||||
<i class="fa fa-file-alt"></i>
|
||||
<span>{{ blog.title }}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="authors-cell">
|
||||
<span class="author-tag" *ngFor="let professor of blog.professors">
|
||||
{{ professor.firstName }}
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="tags-cell">
|
||||
<span class="tag" *ngFor="let tag of blog.tags">
|
||||
{{ tag }}
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<span class="status-badge" [class.status-published]="blog.posted" [class.status-draft]="!blog.posted">
|
||||
<i class="fa" [class.fa-check-circle]="blog.posted" [class.fa-clock]="!blog.posted"></i>
|
||||
{{ blog.posted ? 'Published' : 'Draft' }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<div class="action-buttons">
|
||||
<button class="btn-action btn-edit" (click)="editBlog(blog)" title="Edit">
|
||||
<i class="fa fa-edit"></i>
|
||||
</button>
|
||||
<button class="btn-action btn-delete" (click)="deleteBlog(blog)" title="Delete">
|
||||
<i class="fa fa-trash-alt"></i>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Empty State -->
|
||||
<div *ngIf="blogs.length === 0" class="empty-state">
|
||||
<div class="empty-icon">
|
||||
<i class="fa fa-inbox"></i>
|
||||
</div>
|
||||
<h3>No blogs yet</h3>
|
||||
<p>Get started by creating your first blog post</p>
|
||||
<button class="btn-primary" (click)="showForm()">
|
||||
<i class="fa fa-plus"></i>
|
||||
<span>Create First Blog</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user