diff --git a/backend/src/main/java/es/adeptusminiaturium/backend/model/Media.java b/backend/src/main/java/es/adeptusminiaturium/backend/model/Media.java index 5a651d7..f6a9e04 100644 --- a/backend/src/main/java/es/adeptusminiaturium/backend/model/Media.java +++ b/backend/src/main/java/es/adeptusminiaturium/backend/model/Media.java @@ -1,4 +1,86 @@ package es.adeptusminiaturium.backend.model; +import com.fasterxml.jackson.annotation.JsonManagedReference; +import es.adeptusminiaturium.backend.enums.MediaType; +import jakarta.persistence.*; +import org.hibernate.annotations.CreationTimestamp; + +import java.time.LocalDateTime; +import java.time.LocalDateTime; + +@Entity +@Table(name = "media") public class Media { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "media_id") + private Long mediaId; + + @JsonManagedReference + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "post_id", nullable = false) + private Post post; + + @Enumerated(EnumType.ORDINAL) + @Column(name = "media_type", nullable = false) + private MediaType mediaType = MediaType.IMAGE; + + @Column(nullable = false, length = 512) + private String url; + + @Column(nullable = false) + private Integer position = 0; + + @CreationTimestamp + @Column(name = "created_at", insertable = false, updatable = false) + private LocalDateTime createdAt; + + public Long getMediaId() { + return mediaId; + } + + public void setMediaId(Long mediaId) { + this.mediaId = mediaId; + } + + public Post getPost() { + return post; + } + + public void setPost(Post post) { + this.post = post; + } + + public MediaType getMediaType() { + return mediaType; + } + + public void setMediaType(MediaType mediaType) { + this.mediaType = mediaType; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public Integer getPosition() { + return position; + } + + public void setPosition(Integer position) { + this.position = position; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(LocalDateTime createdAt) { + this.createdAt = createdAt; + } } diff --git a/backend/src/main/java/es/adeptusminiaturium/backend/model/Post.java b/backend/src/main/java/es/adeptusminiaturium/backend/model/Post.java index abe1325..7f354ee 100644 --- a/backend/src/main/java/es/adeptusminiaturium/backend/model/Post.java +++ b/backend/src/main/java/es/adeptusminiaturium/backend/model/Post.java @@ -1,4 +1,143 @@ package es.adeptusminiaturium.backend.model; +import com.fasterxml.jackson.annotation.JsonManagedReference; +import es.adeptusminiaturium.backend.enums.PostStatus; +import jakarta.persistence.*; +import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.annotations.UpdateTimestamp; + +import java.time.LocalDateTime; +import java.util.List; + +@Entity +@Table(name = "posts") public class Post { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "post_id") + private Long postId; + + @JsonManagedReference + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "author_id", nullable = false) + private User author; + + @Column(nullable = false) + private String title; + + @Column(columnDefinition = "TEXT") + private String body; + + @Column(columnDefinition = "TEXT") + private String hashtags; + + @Enumerated(EnumType.ORDINAL) + @Column(nullable = false) + private PostStatus status = PostStatus.DRAFT; + + @Column(name = "published_at") + private LocalDateTime publishedAt; + + @CreationTimestamp + @Column(name = "created_at", insertable = false, updatable = false) + private LocalDateTime createdAt; + + @UpdateTimestamp + @Column(name = "updated_at", insertable = false, updatable = false) + private LocalDateTime updatedAt; + + @OneToMany(mappedBy = "post", cascade = CascadeType.ALL, orphanRemoval = true) + private List media; + + @OneToMany(mappedBy = "post", cascade = CascadeType.ALL, orphanRemoval = true) + private List publications; + + public Long getPostId() { + return postId; + } + + public void setPostId(Long postId) { + this.postId = postId; + } + + public User getAuthor() { + return author; + } + + public void setAuthor(User author) { + this.author = author; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + public String getHashtags() { + return hashtags; + } + + public void setHashtags(String hashtags) { + this.hashtags = hashtags; + } + + public PostStatus getStatus() { + return status; + } + + public void setStatus(PostStatus status) { + this.status = status; + } + + public LocalDateTime getPublishedAt() { + return publishedAt; + } + + public void setPublishedAt(LocalDateTime publishedAt) { + this.publishedAt = publishedAt; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(LocalDateTime createdAt) { + this.createdAt = createdAt; + } + + public LocalDateTime getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(LocalDateTime updatedAt) { + this.updatedAt = updatedAt; + } + + public List getMedia() { + return media; + } + + public void setMedia(List media) { + this.media = media; + } + + public List getPublications() { + return publications; + } + + public void setPublications(List publications) { + this.publications = publications; + } } diff --git a/backend/src/main/java/es/adeptusminiaturium/backend/model/Publication.java b/backend/src/main/java/es/adeptusminiaturium/backend/model/Publication.java index 487e5c5..85fa64f 100644 --- a/backend/src/main/java/es/adeptusminiaturium/backend/model/Publication.java +++ b/backend/src/main/java/es/adeptusminiaturium/backend/model/Publication.java @@ -1,4 +1,111 @@ package es.adeptusminiaturium.backend.model; +import com.fasterxml.jackson.annotation.JsonManagedReference; +import es.adeptusminiaturium.backend.enums.Platform; +import es.adeptusminiaturium.backend.enums.PublicationStatus; +import jakarta.persistence.*; +import org.hibernate.annotations.CreationTimestamp; + +import java.time.LocalDateTime; + +@Entity +@Table( + name = "publications", + uniqueConstraints = @UniqueConstraint(columnNames = {"post_id", "platform"}) +) public class Publication { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "publication_id") + private Long publicationId; + + @JsonManagedReference + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "post_id", nullable = false) + private Post post; + + @Enumerated(EnumType.ORDINAL) + @Column(nullable = false) + private Platform platform; + + private String externalId; + + @Enumerated(EnumType.ORDINAL) + @Column(nullable = false) + private PublicationStatus status = PublicationStatus.PENDING; + + @Column(name = "published_at") + private LocalDateTime publishedAt; + + @Column(columnDefinition = "TEXT") + private String errorMessage; + + @CreationTimestamp + @Column(name = "created_at", insertable = false, updatable = false) + private LocalDateTime createdAt; + + public Long getPublicationId() { + return publicationId; + } + + public void setPublicationId(Long publicationId) { + this.publicationId = publicationId; + } + + public Post getPost() { + return post; + } + + public void setPost(Post post) { + this.post = post; + } + + public Platform getPlatform() { + return platform; + } + + public void setPlatform(Platform platform) { + this.platform = platform; + } + + public String getExternalId() { + return externalId; + } + + public void setExternalId(String externalId) { + this.externalId = externalId; + } + + public PublicationStatus getStatus() { + return status; + } + + public void setStatus(PublicationStatus status) { + this.status = status; + } + + public LocalDateTime getPublishedAt() { + return publishedAt; + } + + public void setPublishedAt(LocalDateTime publishedAt) { + this.publishedAt = publishedAt; + } + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(LocalDateTime createdAt) { + this.createdAt = createdAt; + } } diff --git a/backend/src/main/java/es/adeptusminiaturium/backend/model/User.java b/backend/src/main/java/es/adeptusminiaturium/backend/model/User.java index a189afb..3054c68 100644 --- a/backend/src/main/java/es/adeptusminiaturium/backend/model/User.java +++ b/backend/src/main/java/es/adeptusminiaturium/backend/model/User.java @@ -1,4 +1,118 @@ package es.adeptusminiaturium.backend.model; +import es.adeptusminiaturium.backend.enums.UserRole; +import es.adeptusminiaturium.backend.enums.UserStatus; +import jakarta.persistence.*; +import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.annotations.UpdateTimestamp; + +import java.time.LocalDateTime; +import java.util.UUID; + +@Entity +@Table(name = "users") public class User { + + @Id + @Column(name = "user_id", nullable = false, updatable = false) + private UUID userId; + + @Column(name = "display_name") + private String displayName; + + @Column(name = "user_name", nullable = false, unique = true) + private String userName; + + @Column(nullable = false) + private String password; + + private String avatar; + + @Enumerated(EnumType.ORDINAL) + @Column(nullable = false) + private UserRole role = UserRole.USER; + + @Enumerated(EnumType.ORDINAL) + @Column(nullable = false) + private UserStatus status = UserStatus.ACTIVE; + + @CreationTimestamp + @Column(name = "created_at", insertable = false, updatable = false) + private LocalDateTime createdAt; + + @UpdateTimestamp + @Column(name = "updated_at", insertable = false, updatable = false) + private LocalDateTime updatedAt; + + public UUID getUserId() { + return userId; + } + + public void setUserId(UUID userId) { + this.userId = userId; + } + + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public UserRole getRole() { + return role; + } + + public void setRole(UserRole role) { + this.role = role; + } + + public UserStatus getStatus() { + return status; + } + + public void setStatus(UserStatus status) { + this.status = status; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(LocalDateTime createdAt) { + this.createdAt = createdAt; + } + + public LocalDateTime getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(LocalDateTime updatedAt) { + this.updatedAt = updatedAt; + } } diff --git a/backend/src/main/resources/application-dev.yaml b/backend/src/main/resources/application-dev.yaml index 9d618c1..b4c96ee 100644 --- a/backend/src/main/resources/application-dev.yaml +++ b/backend/src/main/resources/application-dev.yaml @@ -1,9 +1,9 @@ server: port: 8080 - servlet: - context-path: /v1/ spring: + jpa: + show-sql: true datasource: url: jdbc:mariadb://localhost:3306/miniaturium username: admin diff --git a/backend/src/main/resources/application-prod.yaml b/backend/src/main/resources/application-prod.yaml index 87c6604..40b1330 100644 --- a/backend/src/main/resources/application-prod.yaml +++ b/backend/src/main/resources/application-prod.yaml @@ -1,7 +1,5 @@ server: port: 8080 - servlet: - context-path: /v1/ spring: datasource: diff --git a/frontend/src/components/Header.jsx b/frontend/src/components/Header.jsx index 96a2f86..8186c49 100644 --- a/frontend/src/components/Header.jsx +++ b/frontend/src/components/Header.jsx @@ -5,7 +5,13 @@ const Header = () => { const { t } = useTranslation(); return ( -
+
+ Purity Seal +

Adeptus Miniaturium

{t("header.subtitle")}

diff --git a/frontend/src/css/Header.css b/frontend/src/css/Header.css index 21bdc65..8a8e410 100644 --- a/frontend/src/css/Header.css +++ b/frontend/src/css/Header.css @@ -6,6 +6,28 @@ header { box-shadow: 0 10px 30px rgba(0,0,0,0.9); } +.imperial-header { + overflow: visible; + z-index: 1000; +} + +.purity-seal { + position: absolute; + top: 5px; + width: 196px; + z-index: 10; + pointer-events: none; +} + +.purity-seal.left { + left: 8%; +} + +.purity-seal.right { + right: 5%; + transform: rotate(10deg); +} + header h1 { font-family: 'Cinzel', serif; font-size: 3.5rem;