506 lines
21 KiB
HTML
506 lines
21 KiB
HTML
<div class="publication-layout">
|
|
<!-- Sidebar -->
|
|
<app-menu class="sidebar"></app-menu>
|
|
|
|
<!-- Main Content -->
|
|
<div class="publication-content">
|
|
<!-- Header Section -->
|
|
<div class="publication-header">
|
|
<div class="header-left">
|
|
<h1 class="page-title">Publications Management</h1>
|
|
<p class="page-subtitle">Manage academic publications and research papers</p>
|
|
</div>
|
|
<div class="header-actions">
|
|
<div class="search-box">
|
|
<i class="fa fa-search"></i>
|
|
<input
|
|
name="searchTerm"
|
|
#searchTerm="ngModel"
|
|
class="search-input"
|
|
type="search"
|
|
placeholder="Search publications..."
|
|
ngModel
|
|
(ngModelChange)="searchPublications(searchTerm.value)">
|
|
</div>
|
|
<button *ngIf="isManager" class="btn-primary" data-bs-toggle="modal" data-bs-target="#addPublicationModal">
|
|
<i class="fa fa-plus"></i>
|
|
<span>New Publication</span>
|
|
</button>
|
|
<button class="btn-refresh" (click)="getPublications(true)">
|
|
<i class="fas fa-sync" [ngClass]="{'fa-spin': refreshing }"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Filters -->
|
|
<div class="filters-section">
|
|
<div class="filter-group">
|
|
<label><i class="fa fa-tag"></i> Category:</label>
|
|
<select [(ngModel)]="selectedCategory" (change)="onCategoryChange()" class="filter-select">
|
|
<option *ngFor="let cat of categories" [value]="cat">{{cat}}</option>
|
|
</select>
|
|
</div>
|
|
<div class="filter-group">
|
|
<label><i class="fa fa-calendar"></i> Year:</label>
|
|
<select [(ngModel)]="selectedYear" (change)="onYearChange()" class="filter-select">
|
|
<option value="All">All Years</option>
|
|
<option *ngFor="let year of years" [value]="year">{{year}}</option>
|
|
</select>
|
|
</div>
|
|
<div class="results-count">
|
|
Showing {{publications.length}} publication{{publications.length !== 1 ? 's' : ''}}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Publications List -->
|
|
<div class="publications-list" *ngIf="publications && publications.length > 0">
|
|
<div *ngFor="let publication of publications"
|
|
class="publication-card"
|
|
[class.inactive]="!publication?.isActive">
|
|
|
|
<div class="publication-content-area" (click)="publication && onSelectPublication(publication)">
|
|
<div class="publication-header-row">
|
|
<div class="publication-meta">
|
|
<span class="year-badge">{{publication?.year}}</span>
|
|
<span class="category-badge" *ngIf="publication?.category">{{publication.category}}</span>
|
|
<span class="status-badge"
|
|
[class.status-active]="publication?.isActive"
|
|
[class.status-inactive]="!publication?.isActive">
|
|
<i class="fa"
|
|
[class.fa-check-circle]="publication?.isActive"
|
|
[class.fa-times-circle]="!publication?.isActive"></i>
|
|
{{publication?.isActive ? 'Active' : 'Inactive'}}
|
|
</span>
|
|
</div>
|
|
<div class="order-badge">Order: {{publication?.displayOrder}}</div>
|
|
</div>
|
|
|
|
<h3 class="publication-title">{{publication?.title}}</h3>
|
|
|
|
<div class="publication-details">
|
|
<div class="detail-item">
|
|
<i class="fa fa-users"></i>
|
|
<span class="authors-text">{{publication?.authors}}</span>
|
|
</div>
|
|
<div class="detail-item">
|
|
<i class="fa fa-book"></i>
|
|
<span>{{publication?.journal}}</span>
|
|
</div>
|
|
<div class="detail-item" *ngIf="publication?.doi">
|
|
<i class="fa fa-link"></i>
|
|
<a [href]="publication.doi" target="_blank" class="doi-link" (click)="$event.stopPropagation()">
|
|
{{publication.doi}}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="publication-actions">
|
|
<button class="btn-action btn-toggle"
|
|
(click)="onToggleActive(publication); $event.stopPropagation()"
|
|
[title]="publication?.isActive ? 'Set Inactive' : 'Set Active'">
|
|
<i class="fas" [class.fa-toggle-on]="publication?.isActive" [class.fa-toggle-off]="!publication?.isActive"></i>
|
|
</button>
|
|
<button class="btn-action btn-edit"
|
|
(click)="onEditPublication(publication); $event.stopPropagation()"
|
|
title="Edit">
|
|
<i class="fas fa-edit"></i>
|
|
</button>
|
|
<button *ngIf="isAdmin"
|
|
class="btn-action btn-delete"
|
|
(click)="onDeletePublication(publication); $event.stopPropagation()"
|
|
title="Delete">
|
|
<i class="fas fa-trash"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Loading State -->
|
|
<div *ngIf="refreshing" class="loading-state">
|
|
<div class="loading-spinner">
|
|
<i class="fas fa-spinner fa-spin"></i>
|
|
</div>
|
|
<p>Loading publications...</p>
|
|
</div>
|
|
|
|
<!-- Empty State -->
|
|
<div *ngIf="!refreshing && (!publications || publications.length === 0)" class="empty-state">
|
|
<div class="empty-icon">
|
|
<i class="fa fa-book-open"></i>
|
|
</div>
|
|
<h3>No publications yet</h3>
|
|
<p>Get started by creating your first publication</p>
|
|
<button *ngIf="isManager" class="btn-primary" data-bs-toggle="modal" data-bs-target="#addPublicationModal">
|
|
<i class="fa fa-plus"></i>
|
|
<span>Create Your First Publication</span>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Hidden Modal Triggers -->
|
|
<button [hidden]="true" type="button" id="openPublicationInfo" data-bs-toggle="modal" data-bs-target="#viewPublicationModal"></button>
|
|
<button [hidden]="true" type="button" id="openPublicationEdit" data-bs-toggle="modal" data-bs-target="#editPublicationModal"></button>
|
|
|
|
<!-- View Publication Modal -->
|
|
<div class="modal fade" id="viewPublicationModal" tabindex="-1">
|
|
<div class="modal-dialog modal-xl">
|
|
<div class="modal-content" *ngIf="selectedPublication">
|
|
<div class="modal-header">
|
|
<h3>Publication Details</h3>
|
|
<button class="modal-close" data-bs-dismiss="modal">
|
|
<i class="fa fa-times"></i>
|
|
</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="publication-detail-card">
|
|
<!-- Title -->
|
|
<div class="detail-section">
|
|
<h4>Title</h4>
|
|
<p>{{selectedPublication.title}}</p>
|
|
</div>
|
|
|
|
<!-- Authors -->
|
|
<div class="detail-section">
|
|
<h4>Authors</h4>
|
|
<div class="authors-list">
|
|
<span *ngFor="let author of getAuthorsList(selectedPublication.authors)" class="author-chip">
|
|
{{author}}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Year & Journal -->
|
|
<div class="detail-row">
|
|
<div class="detail-section">
|
|
<h4>Year</h4>
|
|
<p>{{selectedPublication.year}}</p>
|
|
</div>
|
|
<div class="detail-section">
|
|
<h4>Journal</h4>
|
|
<p>{{selectedPublication.journal}}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- DOI -->
|
|
<div class="detail-section" *ngIf="selectedPublication.doi">
|
|
<h4>DOI</h4>
|
|
<a [href]="selectedPublication.doi" target="_blank" class="doi-link-large">
|
|
{{selectedPublication.doi}}
|
|
</a>
|
|
</div>
|
|
|
|
<!-- Category & Publication Date -->
|
|
<div class="detail-row">
|
|
<div class="detail-section" *ngIf="selectedPublication.category">
|
|
<h4>Category</h4>
|
|
<span class="category-badge-large">{{selectedPublication.category}}</span>
|
|
</div>
|
|
<div class="detail-section" *ngIf="selectedPublication.publicationDate">
|
|
<h4>Publication Date</h4>
|
|
<p>{{selectedPublication.publicationDate}}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Abstract -->
|
|
<div class="detail-section" *ngIf="selectedPublication.abstractText">
|
|
<h4>Abstract</h4>
|
|
<p class="abstract-text">{{selectedPublication.abstractText}}</p>
|
|
</div>
|
|
|
|
<!-- Keywords -->
|
|
<div class="detail-section" *ngIf="selectedPublication.keywords">
|
|
<h4>Keywords</h4>
|
|
<div class="keywords-list">
|
|
<span *ngFor="let keyword of getKeywordsList(selectedPublication.keywords)" class="keyword-chip">
|
|
{{keyword}}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Status & Order -->
|
|
<div class="detail-row">
|
|
<div class="detail-section">
|
|
<h4>Status</h4>
|
|
<span class="status-badge"
|
|
[class.status-active]="selectedPublication.isActive"
|
|
[class.status-inactive]="!selectedPublication.isActive">
|
|
{{selectedPublication.isActive ? 'Active' : 'Inactive'}}
|
|
</span>
|
|
</div>
|
|
<div class="detail-section">
|
|
<h4>Display Order</h4>
|
|
<p>{{selectedPublication.displayOrder}}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn-secondary" data-bs-dismiss="modal">Close</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Add Publication Modal -->
|
|
<div *ngIf="isManager" class="modal fade" id="addPublicationModal" tabindex="-1">
|
|
<div class="modal-dialog modal-xl">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h3>Add New Publication</h3>
|
|
<button class="modal-close" data-bs-dismiss="modal">
|
|
<i class="fa fa-times"></i>
|
|
</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form #newPublicationForm="ngForm" (ngSubmit)="onAddNewPublication(newPublicationForm)">
|
|
|
|
<div class="form-section">
|
|
<h4 class="section-title">Basic Information</h4>
|
|
|
|
<div class="form-group">
|
|
<label for="title">
|
|
<i class="fa fa-heading"></i>
|
|
Title *
|
|
</label>
|
|
<textarea id="title" name="title" class="form-textarea" rows="3" ngModel required placeholder="Enter publication title"></textarea>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="authors">
|
|
<i class="fa fa-users"></i>
|
|
Authors * (comma-separated)
|
|
</label>
|
|
<textarea id="authors" name="authors" class="form-textarea" rows="2" ngModel required placeholder="Smith, J., Doe, A., Johnson, B."></textarea>
|
|
<small class="form-text">Separate multiple authors with commas</small>
|
|
</div>
|
|
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label for="year">
|
|
<i class="fa fa-calendar"></i>
|
|
Year *
|
|
</label>
|
|
<input type="number" id="year" name="year" class="form-input" ngModel required min="1900" max="2100" placeholder="2024">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="journal">
|
|
<i class="fa fa-book"></i>
|
|
Journal *
|
|
</label>
|
|
<input type="text" id="journal" name="journal" class="form-input" ngModel required placeholder="Journal name">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-section">
|
|
<h4 class="section-title">Additional Details</h4>
|
|
|
|
<div class="form-group">
|
|
<label for="doi">
|
|
<i class="fa fa-link"></i>
|
|
DOI
|
|
</label>
|
|
<input type="text" id="doi" name="doi" class="form-input" ngModel placeholder="https://doi.org/10.1234/example">
|
|
</div>
|
|
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label for="category">
|
|
<i class="fa fa-tag"></i>
|
|
Category
|
|
</label>
|
|
<select id="category" name="category" class="form-select" ngModel>
|
|
<option value="">Select category...</option>
|
|
<option value="Clinical Research">Clinical Research</option>
|
|
<option value="Case Reports">Case Reports</option>
|
|
<option value="Review">Review</option>
|
|
<option value="Healthcare Systems">Healthcare Systems</option>
|
|
<option value="Meta-Analysis">Meta-Analysis</option>
|
|
<option value="Editorial">Editorial</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="publicationDate">
|
|
<i class="fa fa-calendar-alt"></i>
|
|
Publication Date
|
|
</label>
|
|
<input type="text" id="publicationDate" name="publicationDate" class="form-input" ngModel placeholder="January 2024">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="abstractText">
|
|
<i class="fa fa-align-left"></i>
|
|
Abstract
|
|
</label>
|
|
<textarea id="abstractText" name="abstractText" class="form-textarea" rows="6" ngModel placeholder="Enter abstract text"></textarea>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="keywords">
|
|
<i class="fa fa-tags"></i>
|
|
Keywords (comma-separated)
|
|
</label>
|
|
<textarea id="keywords" name="keywords" class="form-textarea" rows="2" ngModel placeholder="trauma, surgery, emergency"></textarea>
|
|
<small class="form-text">Separate multiple keywords with commas</small>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="displayOrder">
|
|
<i class="fa fa-sort-numeric-up"></i>
|
|
Display Order
|
|
</label>
|
|
<input type="number" id="displayOrder" name="displayOrder" class="form-input" ngModel value="0" placeholder="0">
|
|
<small class="form-text">Lower numbers appear first within the same year</small>
|
|
</div>
|
|
</div>
|
|
|
|
</form>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
|
<button class="btn-primary"
|
|
type="button"
|
|
(click)="newPublicationForm.ngSubmit.emit()"
|
|
[disabled]="newPublicationForm.invalid">
|
|
<i class="fa fa-save"></i>
|
|
Create Publication
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Edit Publication Modal -->
|
|
<div class="modal fade" id="editPublicationModal" tabindex="-1">
|
|
<div class="modal-dialog modal-xl">
|
|
<div class="modal-content" *ngIf="selectedPublication">
|
|
<div class="modal-header">
|
|
<h3>Edit Publication</h3>
|
|
<button class="modal-close" data-bs-dismiss="modal">
|
|
<i class="fa fa-times"></i>
|
|
</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form #editPublicationForm="ngForm" (ngSubmit)="onUpdatePublication(editPublicationForm)">
|
|
|
|
<div class="form-section">
|
|
<h4 class="section-title">Basic Information</h4>
|
|
|
|
<div class="form-group">
|
|
<label for="editTitle">
|
|
<i class="fa fa-heading"></i>
|
|
Title *
|
|
</label>
|
|
<textarea id="editTitle" name="title" class="form-textarea" rows="3" [(ngModel)]="selectedPublication.title" required></textarea>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="editAuthors">
|
|
<i class="fa fa-users"></i>
|
|
Authors * (comma-separated)
|
|
</label>
|
|
<textarea id="editAuthors" name="authors" class="form-textarea" rows="2" [(ngModel)]="selectedPublication.authors" required></textarea>
|
|
<small class="form-text">Separate multiple authors with commas</small>
|
|
</div>
|
|
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label for="editYear">
|
|
<i class="fa fa-calendar"></i>
|
|
Year *
|
|
</label>
|
|
<input type="number" id="editYear" name="year" class="form-input" [(ngModel)]="selectedPublication.year" required min="1900" max="2100">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="editJournal">
|
|
<i class="fa fa-book"></i>
|
|
Journal *
|
|
</label>
|
|
<input type="text" id="editJournal" name="journal" class="form-input" [(ngModel)]="selectedPublication.journal" required>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-section">
|
|
<h4 class="section-title">Additional Details</h4>
|
|
|
|
<div class="form-group">
|
|
<label for="editDoi">
|
|
<i class="fa fa-link"></i>
|
|
DOI
|
|
</label>
|
|
<input type="text" id="editDoi" name="doi" class="form-input" [(ngModel)]="selectedPublication.doi">
|
|
</div>
|
|
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label for="editCategory">
|
|
<i class="fa fa-tag"></i>
|
|
Category
|
|
</label>
|
|
<select id="editCategory" name="category" class="form-select" [(ngModel)]="selectedPublication.category">
|
|
<option value="">Select category...</option>
|
|
<option value="Clinical Research">Clinical Research</option>
|
|
<option value="Case Reports">Case Reports</option>
|
|
<option value="Review">Review</option>
|
|
<option value="Healthcare Systems">Healthcare Systems</option>
|
|
<option value="Meta-Analysis">Meta-Analysis</option>
|
|
<option value="Editorial">Editorial</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="editPublicationDate">
|
|
<i class="fa fa-calendar-alt"></i>
|
|
Publication Date
|
|
</label>
|
|
<input type="text" id="editPublicationDate" name="publicationDate" class="form-input" [(ngModel)]="selectedPublication.publicationDate">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="editAbstractText">
|
|
<i class="fa fa-align-left"></i>
|
|
Abstract
|
|
</label>
|
|
<textarea id="editAbstractText" name="abstractText" class="form-textarea" rows="6" [(ngModel)]="selectedPublication.abstractText"></textarea>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="editKeywords">
|
|
<i class="fa fa-tags"></i>
|
|
Keywords (comma-separated)
|
|
</label>
|
|
<textarea id="editKeywords" name="keywords" class="form-textarea" rows="2" [(ngModel)]="selectedPublication.keywords"></textarea>
|
|
<small class="form-text">Separate multiple keywords with commas</small>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="editDisplayOrder">
|
|
<i class="fa fa-sort-numeric-up"></i>
|
|
Display Order
|
|
</label>
|
|
<input type="number" id="editDisplayOrder" name="displayOrder" class="form-input" [(ngModel)]="selectedPublication.displayOrder">
|
|
<small class="form-text">Lower numbers appear first within the same year</small>
|
|
</div>
|
|
</div>
|
|
|
|
</form>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
|
<button class="btn-primary" (click)="editPublicationForm.ngSubmit.emit()" [disabled]="editPublicationForm.invalid">
|
|
<i class="fa fa-save"></i>
|
|
Save Changes
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div> |