publication added newly
This commit is contained in:
@ -0,0 +1,140 @@
|
||||
package net.shyshkin.study.fullstack.supportportal.backend.resource;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.shyshkin.study.fullstack.supportportal.backend.domain.HttpResponse;
|
||||
import net.shyshkin.study.fullstack.supportportal.backend.domain.Publication;
|
||||
import net.shyshkin.study.fullstack.supportportal.backend.service.PublicationService;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/publications")
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
@CrossOrigin
|
||||
public class PublicationResource {
|
||||
|
||||
private final PublicationService publicationService;
|
||||
|
||||
@PostMapping
|
||||
@PreAuthorize("hasAnyAuthority('user:create')")
|
||||
public ResponseEntity<Publication> addPublication(
|
||||
@RequestParam String title,
|
||||
@RequestParam String authors,
|
||||
@RequestParam Integer year,
|
||||
@RequestParam String journal,
|
||||
@RequestParam(required = false) String doi,
|
||||
@RequestParam(required = false) String category,
|
||||
@RequestParam(required = false) String abstractText,
|
||||
@RequestParam(required = false) String publicationDate,
|
||||
@RequestParam(required = false) String keywords,
|
||||
@RequestParam(required = false) Integer displayOrder) {
|
||||
|
||||
log.info("Adding new publication: {}", title);
|
||||
Publication publication = publicationService.addPublication(
|
||||
title, authors, year, journal, doi, category, abstractText, publicationDate, keywords, displayOrder
|
||||
);
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(publication);
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
@PreAuthorize("hasAnyAuthority('user:update')")
|
||||
public ResponseEntity<Publication> updatePublication(
|
||||
@PathVariable Long id,
|
||||
@RequestParam String title,
|
||||
@RequestParam String authors,
|
||||
@RequestParam Integer year,
|
||||
@RequestParam String journal,
|
||||
@RequestParam(required = false) String doi,
|
||||
@RequestParam(required = false) String category,
|
||||
@RequestParam(required = false) String abstractText,
|
||||
@RequestParam(required = false) String publicationDate,
|
||||
@RequestParam(required = false) String keywords,
|
||||
@RequestParam(required = false) Integer displayOrder) {
|
||||
|
||||
log.info("Updating publication with id: {}", id);
|
||||
Publication publication = publicationService.updatePublication(
|
||||
id, title, authors, year, journal, doi, category, abstractText, publicationDate, keywords, displayOrder
|
||||
);
|
||||
return ResponseEntity.ok(publication);
|
||||
}
|
||||
|
||||
@GetMapping("/active")
|
||||
public ResponseEntity<List<Publication>> getActivePublications() {
|
||||
log.info("Getting active publications");
|
||||
List<Publication> publications = publicationService.getActivePublications();
|
||||
return ResponseEntity.ok(publications);
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public ResponseEntity<Publication> getPublicationById(@PathVariable Long id) {
|
||||
log.info("Getting publication with id: {}", id);
|
||||
Publication publication = publicationService.getPublicationById(id);
|
||||
return ResponseEntity.ok(publication);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@PreAuthorize("hasAnyAuthority('user:read')")
|
||||
public ResponseEntity<List<Publication>> getAllPublications() {
|
||||
log.info("Getting all publications");
|
||||
List<Publication> publications = publicationService.getAllPublications();
|
||||
return ResponseEntity.ok(publications);
|
||||
}
|
||||
|
||||
@GetMapping("/category/{category}")
|
||||
public ResponseEntity<List<Publication>> getPublicationsByCategory(@PathVariable String category) {
|
||||
log.info("Getting publications by category: {}", category);
|
||||
List<Publication> publications = publicationService.getPublicationsByCategory(category);
|
||||
return ResponseEntity.ok(publications);
|
||||
}
|
||||
|
||||
@GetMapping("/year/{year}")
|
||||
public ResponseEntity<List<Publication>> getPublicationsByYear(@PathVariable Integer year) {
|
||||
log.info("Getting publications by year: {}", year);
|
||||
List<Publication> publications = publicationService.getPublicationsByYear(year);
|
||||
return ResponseEntity.ok(publications);
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
@PreAuthorize("hasAnyAuthority('user:delete')")
|
||||
public ResponseEntity<HttpResponse> deletePublication(@PathVariable Long id) {
|
||||
log.info("Deleting publication with id: {}", id);
|
||||
publicationService.deletePublication(id);
|
||||
return ResponseEntity.ok(
|
||||
HttpResponse.builder()
|
||||
.httpStatusCode(HttpStatus.OK.value())
|
||||
.httpStatus(HttpStatus.OK)
|
||||
.reason(HttpStatus.OK.getReasonPhrase())
|
||||
.message("Publication deleted successfully")
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
@PutMapping("/{id}/toggle-active")
|
||||
@PreAuthorize("hasAnyAuthority('user:update')")
|
||||
public ResponseEntity<Publication> toggleActiveStatus(@PathVariable Long id) {
|
||||
log.info("Toggling active status for publication with id: {}", id);
|
||||
Publication publication = publicationService.toggleActiveStatus(id);
|
||||
return ResponseEntity.ok(publication);
|
||||
}
|
||||
|
||||
@PutMapping("/reorder")
|
||||
@PreAuthorize("hasAnyAuthority('user:update')")
|
||||
public ResponseEntity<HttpResponse> reorderPublications(@RequestBody List<Long> orderedIds) {
|
||||
log.info("Reordering publications");
|
||||
publicationService.reorderPublications(orderedIds);
|
||||
return ResponseEntity.ok(
|
||||
HttpResponse.builder()
|
||||
.httpStatusCode(HttpStatus.OK.value())
|
||||
.httpStatus(HttpStatus.OK)
|
||||
.reason(HttpStatus.OK.getReasonPhrase())
|
||||
.message("Publications reordered successfully")
|
||||
.build()
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,74 @@
|
||||
package net.shyshkin.study.fullstack.supportportal.backend.domain;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Entity
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "publications")
|
||||
public class Publication implements Serializable {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(nullable = false, updatable = false)
|
||||
private Long id;
|
||||
|
||||
@Column(columnDefinition = "TEXT", nullable = false)
|
||||
private String title;
|
||||
|
||||
@Column(columnDefinition = "TEXT")
|
||||
private String authors; // Stored as comma-separated string
|
||||
|
||||
@Column(nullable = false)
|
||||
private Integer year;
|
||||
|
||||
@Column(columnDefinition = "TEXT", nullable = false)
|
||||
private String journal;
|
||||
|
||||
@Column(columnDefinition = "TEXT")
|
||||
private String doi;
|
||||
|
||||
@Column(length = 100)
|
||||
private String category;
|
||||
|
||||
@Column(columnDefinition = "LONGTEXT")
|
||||
private String abstractText;
|
||||
|
||||
@Column(length = 100)
|
||||
private String publicationDate;
|
||||
|
||||
@Column(columnDefinition = "TEXT")
|
||||
private String keywords; // Stored as comma-separated string
|
||||
|
||||
@JsonProperty("isActive")
|
||||
@Column(name = "is_active")
|
||||
private boolean isActive;
|
||||
|
||||
@Column(name = "display_order")
|
||||
private Integer displayOrder;
|
||||
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date createdDate;
|
||||
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date lastModified;
|
||||
|
||||
@PrePersist
|
||||
protected void onCreate() {
|
||||
createdDate = new Date();
|
||||
lastModified = new Date();
|
||||
}
|
||||
|
||||
@PreUpdate
|
||||
protected void onUpdate() {
|
||||
lastModified = new Date();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
package net.shyshkin.study.fullstack.supportportal.backend.exception.domain;
|
||||
|
||||
public class PublicationNotFoundException extends RuntimeException {
|
||||
|
||||
public PublicationNotFoundException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
package net.shyshkin.study.fullstack.supportportal.backend.repository;
|
||||
|
||||
import net.shyshkin.study.fullstack.supportportal.backend.domain.Publication;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface PublicationRepository extends JpaRepository<Publication, Long> {
|
||||
|
||||
@Query("SELECT p FROM Publication p WHERE p.isActive = true ORDER BY p.year DESC, p.displayOrder ASC, p.id DESC")
|
||||
List<Publication> findByIsActiveTrueOrderByYearDesc();
|
||||
|
||||
@Query("SELECT p FROM Publication p ORDER BY p.year DESC, p.displayOrder ASC, p.id DESC")
|
||||
List<Publication> findAllOrderByYearDesc();
|
||||
|
||||
List<Publication> findByCategory(String category);
|
||||
|
||||
List<Publication> findByYear(Integer year);
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
package net.shyshkin.study.fullstack.supportportal.backend.service;
|
||||
|
||||
import net.shyshkin.study.fullstack.supportportal.backend.domain.Publication;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface PublicationService {
|
||||
|
||||
Publication addPublication(String title, String authors, Integer year, String journal,
|
||||
String doi, String category, String abstractText,
|
||||
String publicationDate, String keywords, Integer displayOrder);
|
||||
|
||||
Publication updatePublication(Long id, String title, String authors, Integer year,
|
||||
String journal, String doi, String category,
|
||||
String abstractText, String publicationDate,
|
||||
String keywords, Integer displayOrder);
|
||||
|
||||
List<Publication> getActivePublications();
|
||||
|
||||
Publication getPublicationById(Long id);
|
||||
|
||||
List<Publication> getAllPublications();
|
||||
|
||||
List<Publication> getPublicationsByCategory(String category);
|
||||
|
||||
List<Publication> getPublicationsByYear(Integer year);
|
||||
|
||||
void deletePublication(Long id);
|
||||
|
||||
Publication toggleActiveStatus(Long id);
|
||||
|
||||
void reorderPublications(List<Long> orderedIds);
|
||||
}
|
||||
@ -0,0 +1,129 @@
|
||||
package net.shyshkin.study.fullstack.supportportal.backend.service.impl;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.shyshkin.study.fullstack.supportportal.backend.domain.Publication;
|
||||
import net.shyshkin.study.fullstack.supportportal.backend.exception.domain.PublicationNotFoundException;
|
||||
import net.shyshkin.study.fullstack.supportportal.backend.repository.PublicationRepository;
|
||||
import net.shyshkin.study.fullstack.supportportal.backend.service.PublicationService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Transactional
|
||||
public class PublicationServiceImpl implements PublicationService {
|
||||
|
||||
private final PublicationRepository publicationRepository;
|
||||
|
||||
@Override
|
||||
public Publication addPublication(String title, String authors, Integer year, String journal,
|
||||
String doi, String category, String abstractText,
|
||||
String publicationDate, String keywords, Integer displayOrder) {
|
||||
log.info("Adding new publication: {}", title);
|
||||
|
||||
Publication publication = new Publication();
|
||||
publication.setTitle(title);
|
||||
publication.setAuthors(authors);
|
||||
publication.setYear(year);
|
||||
publication.setJournal(journal);
|
||||
publication.setDoi(doi);
|
||||
publication.setCategory(category);
|
||||
publication.setAbstractText(abstractText);
|
||||
publication.setPublicationDate(publicationDate);
|
||||
publication.setKeywords(keywords);
|
||||
publication.setDisplayOrder(displayOrder != null ? displayOrder : 0);
|
||||
publication.setActive(true);
|
||||
|
||||
return publicationRepository.save(publication);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Publication updatePublication(Long id, String title, String authors, Integer year,
|
||||
String journal, String doi, String category,
|
||||
String abstractText, String publicationDate,
|
||||
String keywords, Integer displayOrder) {
|
||||
log.info("Updating publication with id: {}", id);
|
||||
|
||||
Publication publication = getPublicationById(id);
|
||||
publication.setTitle(title);
|
||||
publication.setAuthors(authors);
|
||||
publication.setYear(year);
|
||||
publication.setJournal(journal);
|
||||
publication.setDoi(doi);
|
||||
publication.setCategory(category);
|
||||
publication.setAbstractText(abstractText);
|
||||
publication.setPublicationDate(publicationDate);
|
||||
publication.setKeywords(keywords);
|
||||
|
||||
if (displayOrder != null) {
|
||||
publication.setDisplayOrder(displayOrder);
|
||||
}
|
||||
|
||||
return publicationRepository.save(publication);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public List<Publication> getActivePublications() {
|
||||
return publicationRepository.findByIsActiveTrueOrderByYearDesc();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public Publication getPublicationById(Long id) {
|
||||
return publicationRepository.findById(id)
|
||||
.orElseThrow(() -> new PublicationNotFoundException("Publication not found with id: " + id));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public List<Publication> getAllPublications() {
|
||||
return publicationRepository.findAllOrderByYearDesc();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public List<Publication> getPublicationsByCategory(String category) {
|
||||
return publicationRepository.findByCategory(category);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public List<Publication> getPublicationsByYear(Integer year) {
|
||||
return publicationRepository.findByYear(year);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deletePublication(Long id) {
|
||||
log.info("Deleting publication with id: {}", id);
|
||||
|
||||
Publication publication = getPublicationById(id);
|
||||
publicationRepository.delete(publication);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Publication toggleActiveStatus(Long id) {
|
||||
log.info("Toggling active status for publication with id: {}", id);
|
||||
|
||||
Publication publication = getPublicationById(id);
|
||||
publication.setActive(!publication.isActive());
|
||||
|
||||
return publicationRepository.save(publication);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reorderPublications(List<Long> orderedIds) {
|
||||
log.info("Reordering {} publications", orderedIds.size());
|
||||
|
||||
for (int i = 0; i < orderedIds.size(); i++) {
|
||||
Long id = orderedIds.get(i);
|
||||
Publication publication = getPublicationById(id);
|
||||
publication.setDisplayOrder(i);
|
||||
publicationRepository.save(publication);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -51,7 +51,7 @@ file:
|
||||
app:
|
||||
base-url: ${APP_BASE_URL:http://localhost:8080}
|
||||
# Fixed public URLs with correct wildcard patterns
|
||||
public-urls: /user/login,/user/register,/user/*/profile-image,/user/*/profile-image/**,/professors,/professors/**,/api/posts,/api/posts/*,/api/posts/posted,/api/posts/tag/*,/api/posts/tags/count,/api/files/**,/uploads/**,/professor/**,/api/events,/api/events/*,/api/public/**,/api/jobs/active,/api/job-applications/**,/api/job-applications/resume/**,/api/courses/active,/api/courses/*,/api/course-applications,/api/upcoming-events/active,/api/milestones,/api/milestones/**,/api/testimonials,/api/testimonials/**,/hero/image/**,/hero/active/**,/hero/**,/service-tiles/active,/service-tiles/active/**
|
||||
public-urls: /user/login,/user/register,/user/*/profile-image,/user/*/profile-image/**,/professors,/professors/**,/api/posts,/api/posts/*,/api/posts/posted,/api/posts/tag/*,/api/posts/tags/count,/api/files/**,/uploads/**,/professor/**,/api/events,/api/events/*,/api/public/**,/api/jobs/active,/api/job-applications/**,/api/job-applications/resume/**,/api/courses/active,/api/courses/*,/api/course-applications,/api/upcoming-events/active,/api/milestones,/api/milestones/**,/api/testimonials,/api/testimonials/**,/hero/image/**,/hero/active/**,/hero/**,/service-tiles/active,/service-tiles/active/**,/publications/active/**,/publications/*/**,/publications/category/**,/publications/year/**
|
||||
cors:
|
||||
allowed-origins: http://localhost:4200,http://localhost:3000,https://maincmc.rootxwire.com,https://dashboard.cmctrauma.com,https://www.dashboard.cmctrauma.com,https://cmctrauma.com,https://www.cmctrauma.com,https://cmcbackend.rootxwire.com,https://cmcadminfrontend.rootxwire.com
|
||||
jwt:
|
||||
|
||||
Reference in New Issue
Block a user