diff --git a/src/main/java/de/holarse/backend/db/Article.java b/src/main/java/de/holarse/backend/db/Article.java index 3eeac13b..c8d34c10 100644 --- a/src/main/java/de/holarse/backend/db/Article.java +++ b/src/main/java/de/holarse/backend/db/Article.java @@ -14,7 +14,7 @@ @Table(name = "articles") @Entity -public class Article extends Base { +public class Article extends Base implements Node { private static final long serialVersionUID = 2L; @@ -44,10 +44,12 @@ public class Article extends Base { @JoinColumn(name="nodeid", insertable=false, nullable=false, updatable = false, referencedColumnName = "nodeid") private Set nodeSlugs = new HashSet<>(); + @Override public int getNodeId() { return nodeId; } + @Override public void setNodeId(int nodeId) { this.nodeId = nodeId; } diff --git a/src/main/java/de/holarse/backend/db/News.java b/src/main/java/de/holarse/backend/db/News.java index 6aa180fd..ad7e0a98 100644 --- a/src/main/java/de/holarse/backend/db/News.java +++ b/src/main/java/de/holarse/backend/db/News.java @@ -15,7 +15,7 @@ @Table(name = "news") @Entity -public class News extends Base { +public class News extends Base implements Node { private static final long serialVersionUID = 2L; @@ -24,7 +24,7 @@ public class News extends Base { @OneToOne @JoinColumn(name = "revisionid", referencedColumnName = "id") - private NewsRevision newsRevision; + private NewsRevision nodeRevision; @Column(name = "drupalid") private Integer drupalId; @@ -48,10 +48,12 @@ public class News extends Base { @JoinColumn(name="nodeid", referencedColumnName = "nodeid") private Set nodeSlugz = new HashSet<>(); + @Override public int getNodeId() { return nodeId; } + @Override public void setNodeId(int nodeId) { this.nodeId = nodeId; } @@ -64,12 +66,12 @@ public void setDrupalId(Integer drupalId) { this.drupalId = drupalId; } - public NewsRevision getNewsRevision() { - return newsRevision; + public NewsRevision getNodeRevision() { + return nodeRevision; } - public void setNewsRevision(NewsRevision articleRevision) { - this.newsRevision = newsRevision; + public void setNodeRevision(NewsRevision nodeRevision) { + this.nodeRevision = nodeRevision; } public NodeStatus getNodeStatus() { @@ -100,7 +102,7 @@ public void setNodeSlugz(Set nodeSlugz) { public String toString() { return "News{" + "nodeId=" + nodeId + - ", newsRevision=" + newsRevision + + ", nodeRevision=" + nodeRevision + ", drupalId=" + drupalId + ", nodeStatus=" + nodeStatus + ", tags=" + tags + diff --git a/src/main/java/de/holarse/backend/db/Node.java b/src/main/java/de/holarse/backend/db/Node.java new file mode 100644 index 00000000..cb11affc --- /dev/null +++ b/src/main/java/de/holarse/backend/db/Node.java @@ -0,0 +1,16 @@ +/* + * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license + * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template + */ +package de.holarse.backend.db; + +/** + * + * @author comrad + */ +public interface Node { + + int getNodeId(); + void setNodeId(int nodeId); + +} diff --git a/src/main/java/de/holarse/backend/db/repositories/ArticleRepository.java b/src/main/java/de/holarse/backend/db/repositories/ArticleRepository.java index b2fce974..40a69a26 100644 --- a/src/main/java/de/holarse/backend/db/repositories/ArticleRepository.java +++ b/src/main/java/de/holarse/backend/db/repositories/ArticleRepository.java @@ -19,7 +19,7 @@ @Repository public interface ArticleRepository extends JpaRepository, NodeAwareRepository { - @Query(value = "SELECT nr.nodeId, sl.name as slug, null as nodeType, nr.title1 as title, nr.teaser FROM Article n " + + @Query(value = "SELECT nr.nodeId, sl.name as slug, null as nodeType, nr.title1 as title, nr.teaser, concat('wiki/', sl.name) as url FROM Article n " + "JOIN n.nodeRevision as nr " + "JOIN n.nodeStatus as ns " + "JOIN n.nodeSlugs as sl " + diff --git a/src/main/java/de/holarse/backend/db/repositories/NewsRepository.java b/src/main/java/de/holarse/backend/db/repositories/NewsRepository.java index 36041e48..33f23569 100644 --- a/src/main/java/de/holarse/backend/db/repositories/NewsRepository.java +++ b/src/main/java/de/holarse/backend/db/repositories/NewsRepository.java @@ -1,5 +1,6 @@ package de.holarse.backend.db.repositories; +import de.holarse.backend.db.Article; import de.holarse.backend.db.News; import de.holarse.backend.view.FrontpageItemView; import org.springframework.data.domain.Pageable; @@ -8,14 +9,27 @@ import org.springframework.stereotype.Repository; import java.util.List; +import java.util.Optional; +import org.springframework.data.repository.query.Param; @Repository public interface NewsRepository extends JpaRepository, NodeAwareRepository { - @Query(value = "SELECT nr.nodeId, sl.name as slug, 'news' as nodeType, nr.title as title, nr.teaser FROM News n " - + "JOIN n.newsRevision nr " + @Query(value = "SELECT nr.nodeId, sl.name as slug, 'news' as nodeType, nr.title as title, nr.teaser, concat('news/', sl.name) as url FROM News n " + + "JOIN n.nodeRevision nr " + "JOIN n.nodeStatus as ns " + "JOIN n.nodeSlugz as sl " + "WHERE ns.published and NOT ns.deleted and sl.id = (SELECT max(_sl.id) FROM NodeSlug _sl where _sl.nodeId = n.nodeId)") List findFrontpageItems(final Pageable pageable); + + @Query(value = "FROM News n " + + "JOIN FETCH n.nodeRevision nr " + + "JOIN FETCH n.nodeStatus as ns " + + "JOIN n.nodeSlugz as sl " + + "LEFT JOIN FETCH n.tags " + + "WHERE ns.published and NOT ns.deleted " + + "AND sl.name = :slug") + Optional findBySlug(@Param("slug") final String slug); + + Optional findByNodeId(final Integer nodeId); } diff --git a/src/main/java/de/holarse/backend/view/FrontpageItemView.java b/src/main/java/de/holarse/backend/view/FrontpageItemView.java index 43c14544..74e80853 100644 --- a/src/main/java/de/holarse/backend/view/FrontpageItemView.java +++ b/src/main/java/de/holarse/backend/view/FrontpageItemView.java @@ -7,9 +7,8 @@ public interface FrontpageItemView { Integer getNodeId(); String getSlug(); NodeType getNodeType(); - String getTitle(); - String getTeaser(); + String getUrl(); } diff --git a/src/main/java/de/holarse/backend/view/NewsView.java b/src/main/java/de/holarse/backend/view/NewsView.java new file mode 100644 index 00000000..5212632f --- /dev/null +++ b/src/main/java/de/holarse/backend/view/NewsView.java @@ -0,0 +1,103 @@ +package de.holarse.backend.view; + +import de.holarse.backend.db.NewsCategory; +import de.holarse.backend.db.NewsRevision; +import de.holarse.backend.db.NodeSlug; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author comrad + */ +public class NewsView { + + private String title; + private String teaser; + private String content; + private NewsCategory newsCategory; + private Integer nodeId; + + private String url; + + private List websiteLinks = new ArrayList<>(); + private List youtubeVideos = new ArrayList<>(); + + public static NewsView of(final NewsRevision newsRevision, final NodeSlug slug) { + final NewsView nv = new NewsView(); + nv.title = newsRevision.getTitle(); + nv.teaser = newsRevision.getTeaser(); + nv.content = newsRevision.getContent(); + nv.newsCategory = newsRevision.getNewsCategory(); + nv.nodeId = newsRevision.getNodeId(); + + nv.setUrl(String.format("/news/%s", slug.getName())); + + return nv; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getTeaser() { + return teaser; + } + + public void setTeaser(String teaser) { + this.teaser = teaser; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public NewsCategory getNewsCategory() { + return newsCategory; + } + + public void setNewsCategory(NewsCategory newsCategory) { + this.newsCategory = newsCategory; + } + + public Integer getNodeId() { + return nodeId; + } + + public void setNodeId(Integer nodeId) { + this.nodeId = nodeId; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public List getWebsiteLinks() { + return websiteLinks; + } + + public void setWebsiteLinks(List websiteLinks) { + this.websiteLinks = websiteLinks; + } + + public List getYoutubeVideos() { + return youtubeVideos; + } + + public void setYoutubeVideos(List youtubeVideos) { + this.youtubeVideos = youtubeVideos; + } + +} diff --git a/src/main/java/de/holarse/web/controller/NewsController.java b/src/main/java/de/holarse/web/controller/NewsController.java index 6d43f92a..043dc7be 100644 --- a/src/main/java/de/holarse/web/controller/NewsController.java +++ b/src/main/java/de/holarse/web/controller/NewsController.java @@ -1,6 +1,23 @@ package de.holarse.web.controller; +import de.holarse.backend.db.Attachment; +import de.holarse.backend.db.News; +import de.holarse.backend.db.NewsRevision; +import de.holarse.backend.db.NodeSlug; +import de.holarse.backend.db.NodeStatus; +import de.holarse.backend.db.repositories.AttachmentGroupRepository; +import de.holarse.backend.db.repositories.AttachmentRepository; +import de.holarse.backend.db.repositories.AttachmentTypeRepository; +import de.holarse.backend.db.repositories.NewsCategoryRepository; import de.holarse.backend.db.repositories.NewsRepository; +import de.holarse.backend.db.repositories.NodeSlugRepository; +import de.holarse.backend.types.AttachmentGroupType; +import de.holarse.backend.types.NodeType; +import de.holarse.backend.view.AttachmentView; +import de.holarse.backend.view.NewsView; +import de.holarse.backend.view.SettingsView; +import de.holarse.backend.view.YoutubeView; +import de.holarse.web.controller.commands.NewsForm; import de.holarse.web.defines.WebDefines; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; @@ -11,22 +28,125 @@ import org.springframework.web.servlet.ModelAndView; import static de.holarse.web.defines.WebDefines.NEWS_ARTICLES_DEFAULT_PAGE_SIZE; +import de.holarse.web.renderer.Renderer; +import de.holarse.web.services.AttachmentService; +import jakarta.persistence.EntityNotFoundException; +import java.security.Principal; +import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.servlet.view.RedirectView; @Controller @RequestMapping(value = {"/news", "/news/" }) public class NewsController { + final static transient Logger logger = LoggerFactory.getLogger(NewsController.class); + @Autowired private NewsRepository newsRepository; + + @Autowired + private NodeSlugRepository nodeSlugRepository; + + @Autowired + private Renderer renderer; + + @Autowired + private AttachmentService attachmentService; + + @Autowired + private AttachmentRepository attachmentRepository; + + @Autowired + private AttachmentTypeRepository attachmentTypeRepository; + @Autowired + private AttachmentGroupRepository attachmentGroupRepository; + + @Autowired + private NewsCategoryRepository newsCategoryRepository; + @GetMapping public ModelAndView index(@PageableDefault(sort = {"title"}, value = NEWS_ARTICLES_DEFAULT_PAGE_SIZE) final Pageable pageable, final ModelAndView mv) { mv.setViewName("layouts/bare"); mv.addObject("title", "Die Linuxspiele-Seite für Linuxspieler"); mv.addObject(WebDefines.DEFAULT_VIEW_ATTRIBUTE_NAME, "sites/news/index"); - // TODO: Wieder entfernen, nur zum Testen - //mv.addObject("items", newsRepository.findFrontpageItems(pageable)); + mv.addObject("items", newsRepository.findFrontpageItems(pageable)); return mv; } + + @GetMapping("{slug}") + public ModelAndView show(@PathVariable("slug") final String slug, final ModelAndView mv) { + mv.setViewName("layouts/bare"); + mv.addObject("title", "Die Linuxspiele-Seite für Linuxspieler"); + mv.addObject(WebDefines.DEFAULT_VIEW_ATTRIBUTE_NAME, "sites/news/show"); + + final News news = newsRepository.findBySlug(slug).orElseThrow(EntityNotFoundException::new); + + // NodeStatus auswerten und entscheiden, ob für öffentlich sichtbar + final NodeStatus nodeStatus = news.getNodeStatus(); + + final List websiteLinks = attachmentService.getAttachments(news, attachmentGroupRepository.findByCode(AttachmentGroupType.website.name())); + final List videos = attachmentService.getAttachments(news, attachmentGroupRepository.findByCode(AttachmentGroupType.video.name())); + + final NewsRevision newsRevision = news.getNodeRevision(); + final NodeSlug mainSlug = nodeSlugRepository.findMainSlug(newsRevision.getNodeId(), NodeType.news).orElseThrow(EntityNotFoundException::new); + final NewsView view = NewsView.of(newsRevision, mainSlug); + view.setNodeId(news.getNodeId()); + view.setContent(renderer.render(view.getContent(), null)); + //view.setSlug(mainSlug.getName()); + view.setWebsiteLinks(websiteLinks.stream().map(AttachmentView::of).toList()); + view.setYoutubeVideos(videos.stream().map(YoutubeView::of).toList()); + + mv.addObject("view", view); + + return mv; + } + + /** + * Weiterleitung der lesbaren URL auf die Edit-URL + * @param slug + * @param mv + * @return + */ + @GetMapping(value = "{slug}", params="edit") + public RedirectView edit(@PathVariable final String slug, final ModelAndView mv) { + final News news = newsRepository.findBySlug(slug).orElseThrow(EntityNotFoundException::new); + return new RedirectView(String.format("%d/edit", news.getNodeId())); + } + + @GetMapping(value = "{nodeId}/edit") + public ModelAndView edit(@PathVariable final Integer nodeId, final ModelAndView mv, final Principal principal) { + mv.setViewName("layouts/bare"); + mv.addObject("title", "Die Linuxspiele-Seite für Linuxspieler"); + mv.addObject(WebDefines.DEFAULT_VIEW_ATTRIBUTE_NAME, "sites/news/form"); + + var news = newsRepository.findByNodeId(nodeId).orElseThrow(EntityNotFoundException::new); + var newsRevision = news.getNodeRevision(); + + // Form zusammenstellen + final NewsForm form = new NewsForm(); + form.setNodeId(newsRevision.getNodeId()); + form.setNewsCategoryId(newsRevision.getNewsCategory() != null ? newsRevision.getNewsCategory().getId() : 0); + form.setTitle(newsRevision.getTitle()); + form.setContent(newsRevision.getContent()); + + // Attachments + final List websiteLinks = attachmentService.getAttachments(news, attachmentGroupRepository.findByCode("website")); + logger.debug("Links: {}", websiteLinks); + form.setWebsiteLinks(websiteLinks.stream().map(AttachmentView::of).toList()); + + form.setSettings(SettingsView.of(news.getNodeStatus())); + + logger.debug("WebsiteLinks: {}", form.getWebsiteLinks()); + + + mv.addObject("news_categories", newsCategoryRepository.findActiveCategories()); + + return mv.addObject("form", form); + } + } diff --git a/src/main/java/de/holarse/web/controller/WelcomeController.java b/src/main/java/de/holarse/web/controller/WelcomeController.java index d19cca9b..7689ffcc 100644 --- a/src/main/java/de/holarse/web/controller/WelcomeController.java +++ b/src/main/java/de/holarse/web/controller/WelcomeController.java @@ -1,6 +1,5 @@ package de.holarse.web.controller; -import de.holarse.backend.db.ApiUser; import de.holarse.backend.db.repositories.ApiUserRepository; import de.holarse.backend.db.repositories.ArticleRepository; import de.holarse.backend.db.repositories.NewsRepository; diff --git a/src/main/java/de/holarse/web/controller/WorkspaceController.java b/src/main/java/de/holarse/web/controller/WorkspaceController.java index 23ef626b..9f586fe8 100644 --- a/src/main/java/de/holarse/web/controller/WorkspaceController.java +++ b/src/main/java/de/holarse/web/controller/WorkspaceController.java @@ -155,7 +155,7 @@ public ModelAndView saveNews(@Valid @ModelAttribute("form") final NewsForm form, // News anlegen final News news = new News(); news.setNodeId(nodeId); - news.setNewsRevision(newsRevision); // TODO Referenz auf NewsRevision wird noch nicht gespeichert + news.setNodeRevision(newsRevision); // TODO Referenz auf NewsRevision wird noch nicht gespeichert news.setNodeStatus(nodeStatus); news.getNodeSlugz().add(nodeSlug); diff --git a/src/main/java/de/holarse/web/services/AttachmentService.java b/src/main/java/de/holarse/web/services/AttachmentService.java index 6dfd26b9..81c504e6 100644 --- a/src/main/java/de/holarse/web/services/AttachmentService.java +++ b/src/main/java/de/holarse/web/services/AttachmentService.java @@ -1,11 +1,9 @@ package de.holarse.web.services; -import de.holarse.backend.db.Article; import de.holarse.backend.db.Attachment; import de.holarse.backend.db.AttachmentGroup; -import de.holarse.backend.db.AttachmentType; +import de.holarse.backend.db.Node; import de.holarse.backend.db.repositories.AttachmentRepository; -import jakarta.validation.constraints.NotNull; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.context.annotation.RequestScope; @@ -26,16 +24,16 @@ protected Map> splitAttachments(final List return attachments.stream().collect(Collectors.groupingBy(a -> a.getAttachmentType().getAttachmentGroup().getCode())); } - public List getAttachments(final Article article, final AttachmentGroup attachmentGroup) { - if (article == null) { - throw new IllegalArgumentException("article is null"); + public List getAttachments(final Node node, final AttachmentGroup attachmentGroup) { + if (node == null) { + throw new IllegalArgumentException("node is null"); } if (attachmentGroup == null) { throw new IllegalArgumentException("attachmentGroup is null"); } if (nodeAttachmentGroups.isEmpty()) { - nodeAttachmentGroups.putAll(splitAttachments(attachmentRepository.findByNode(article.getNodeId()))); + nodeAttachmentGroups.putAll(splitAttachments(attachmentRepository.findByNode(node.getNodeId()))); } if (nodeAttachmentGroups.containsKey(attachmentGroup.getCode())) { diff --git a/src/main/webapp/WEB-INF/templates/sites/news/form.html b/src/main/webapp/WEB-INF/templates/sites/news/form.html new file mode 100644 index 00000000..ec8c038c --- /dev/null +++ b/src/main/webapp/WEB-INF/templates/sites/news/form.html @@ -0,0 +1,8 @@ +
+
+ + +
+ +
+
diff --git a/src/main/webapp/WEB-INF/templates/sites/news/show.html b/src/main/webapp/WEB-INF/templates/sites/news/show.html new file mode 100644 index 00000000..e29ac5e5 --- /dev/null +++ b/src/main/webapp/WEB-INF/templates/sites/news/show.html @@ -0,0 +1,35 @@ + +
+
+
+ +
+

Lorem ipsum standard

+

+
+
+

+
+
+
+
+ + +
+

Tags

+
+
    + +
    +

    Links

    +
    +

    +
    +
    + + + diff --git a/src/main/webapp/WEB-INF/templates/sites/welcome.html b/src/main/webapp/WEB-INF/templates/sites/welcome.html index fb34349c..7eebc7ab 100644 --- a/src/main/webapp/WEB-INF/templates/sites/welcome.html +++ b/src/main/webapp/WEB-INF/templates/sites/welcome.html @@ -13,7 +13,7 @@

    Teaser

    InVision

    - Read more + Read more