Skip to content

Commit 1333899

Browse files
committed
Revision-Übersichtsseite und Revision-Detailseite angefangen
1 parent 39246ee commit 1333899

File tree

9 files changed

+203
-10
lines changed

9 files changed

+203
-10
lines changed

src/main/java/de/holarse/backend/db/ArticleRevision.java

+34-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package de.holarse.backend.db;
22

3-
import jakarta.persistence.Column;
4-
import jakarta.persistence.Entity;
5-
import jakarta.persistence.Table;
3+
import jakarta.persistence.*;
64

75
@Table(name = "article_revisions")
86
@Entity
@@ -31,6 +29,16 @@ public class ArticleRevision extends TimestampedBase {
3129
@Column(length = 16384)
3230
private String content;
3331

32+
@OneToOne(cascade = { CascadeType.ALL })
33+
@JoinColumn(name="update_userid", insertable=false, nullable=false, updatable = false, referencedColumnName = "id")
34+
private User author;
35+
36+
@Column(length = 512)
37+
private String teaser;
38+
39+
@Column(length = 255)
40+
private String changelog;
41+
3442
public Integer getNodeId() {
3543
return nodeId;
3644
}
@@ -111,4 +119,27 @@ public void setContent(String content) {
111119
this.content = content;
112120
}
113121

122+
public String getChangelog() {
123+
return changelog;
124+
}
125+
126+
public void setChangelog(String changelog) {
127+
this.changelog = changelog;
128+
}
129+
130+
public String getTeaser() {
131+
return teaser;
132+
}
133+
134+
public void setTeaser(String teaser) {
135+
this.teaser = teaser;
136+
}
137+
138+
public User getAuthor() {
139+
return author;
140+
}
141+
142+
public void setAuthor(User author) {
143+
this.author = author;
144+
}
114145
}

src/main/java/de/holarse/backend/db/repositories/ArticleRevisionRepository.java

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import java.util.Optional;
66
import org.springframework.data.domain.Page;
77
import org.springframework.data.domain.Pageable;
8+
import org.springframework.data.domain.Sort;
89
import org.springframework.data.jpa.repository.JpaRepository;
910
import org.springframework.data.jpa.repository.Query;
1011
import org.springframework.data.repository.query.Param;
@@ -27,4 +28,7 @@ public interface ArticleRevisionRepository extends JpaRepository<ArticleRevision
2728
// "INNER JOIN Article a ON a.nodeId = ar.nodeId " +
2829
// "WHERE ar.nodeId = :nodeId")
2930
// Optional<ArticleRevision> findCurrentByNodeId(@Param("nodeId") final int nodeId);
31+
32+
@Query("from ArticleRevision ar where ar.nodeId = :nodeId")
33+
Page<ArticleRevision> findHistory(@Param("nodeId") final Integer nodeId, final Pageable pageable);
3034
}

src/main/java/de/holarse/backend/view/ArticleView.java

+16-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import de.holarse.backend.db.ArticleRevision;
44
import de.holarse.backend.db.Attachment;
5+
import de.holarse.backend.db.NodeSlug;
56
import org.apache.commons.lang3.StringUtils;
67

78
import java.time.LocalDateTime;
@@ -26,7 +27,10 @@ public class ArticleView {
2627
private String content;
2728
private LocalDateTime created;
2829
private LocalDateTime updated;
29-
30+
31+
// Calculated Values
32+
private transient String url;
33+
3034
// Tags as editable String
3135
private String tags;
3236
// Tags as views for display
@@ -35,7 +39,7 @@ public class ArticleView {
3539
private List<AttachmentView> websiteLinks = new ArrayList<>();
3640
private List<YoutubeView> youtubeVideos = new ArrayList<>();
3741

38-
public static ArticleView of(final ArticleRevision ar) {
42+
public static ArticleView of(final ArticleRevision ar, final NodeSlug slug) {
3943
final ArticleView av = new ArticleView();
4044
av.setNodeId(ar.getNodeId());
4145
av.setTitle1(ar.getTitle1());
@@ -56,6 +60,8 @@ public static ArticleView of(final ArticleRevision ar) {
5660
if (StringUtils.isNotBlank(ar.getTitle6())) { av.getAlternativeTitles().add(ar.getTitle6()); }
5761
if (StringUtils.isNotBlank(ar.getTitle7())) { av.getAlternativeTitles().add(ar.getTitle7()); }
5862

63+
av.setUrl(String.format("/wiki/%s", slug.getName()));
64+
5965
return av;
6066
}
6167

@@ -194,4 +200,12 @@ public List<YoutubeView> getYoutubeVideos() {
194200
public void setYoutubeVideos(List<YoutubeView> youtubeVideos) {
195201
this.youtubeVideos = youtubeVideos;
196202
}
203+
204+
public String getUrl() {
205+
return url;
206+
}
207+
208+
public void setUrl(String url) {
209+
this.url = url;
210+
}
197211
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package de.holarse.web.controller;
2+
3+
import de.holarse.backend.db.Article;
4+
import de.holarse.backend.db.ArticleRevision;
5+
import de.holarse.backend.db.NodeSlug;
6+
import de.holarse.backend.db.repositories.ArticleRepository;
7+
import de.holarse.backend.db.repositories.ArticleRevisionRepository;
8+
import de.holarse.backend.db.repositories.NodeSlugRepository;
9+
import de.holarse.backend.types.NodeType;
10+
import de.holarse.backend.view.ArticleView;
11+
import de.holarse.web.defines.WebDefines;
12+
import jakarta.persistence.EntityNotFoundException;
13+
import org.slf4j.Logger;
14+
import org.slf4j.LoggerFactory;
15+
import org.springframework.beans.factory.annotation.Autowired;
16+
import org.springframework.data.domain.Page;
17+
import org.springframework.data.domain.Pageable;
18+
import org.springframework.data.domain.Sort;
19+
import org.springframework.data.web.PageableDefault;
20+
import org.springframework.stereotype.Controller;
21+
import org.springframework.web.bind.annotation.GetMapping;
22+
import org.springframework.web.bind.annotation.PathVariable;
23+
import org.springframework.web.servlet.ModelAndView;
24+
25+
import static de.holarse.web.defines.WebDefines.REVISION_DEFAULT_PAGE_SIZE;
26+
27+
@Controller
28+
public class RevisionController {
29+
30+
private final static transient Logger logger = LoggerFactory.getLogger(RevisionController.class);
31+
32+
@Autowired
33+
private ArticleRepository articleRepository;
34+
35+
@Autowired
36+
private ArticleRevisionRepository articleRevisionRepository;
37+
38+
@Autowired
39+
private NodeSlugRepository nodeSlugRepository;
40+
41+
@GetMapping("/wiki/{nodeId}/revisions")
42+
public ModelAndView revisions(@PathVariable final Integer nodeId, @PageableDefault(sort={"revision"}, value=REVISION_DEFAULT_PAGE_SIZE, direction = Sort.Direction.DESC) final Pageable pageable, final ModelAndView mv) {
43+
mv.setViewName("layouts/bare");
44+
mv.addObject("title", "Die Linuxspiele-Seite für Linuxspieler");
45+
mv.addObject(WebDefines.DEFAULT_VIEW_ATTRIBUTE_NAME, "sites/revisions/index");
46+
47+
final Article currentArticle = articleRepository.findByNodeId(nodeId).orElseThrow(EntityNotFoundException::new);
48+
final Page<ArticleRevision> revisions = articleRevisionRepository.findHistory(nodeId, pageable);
49+
final NodeSlug mainSlug = nodeSlugRepository.findMainSlug(nodeId, NodeType.article).orElseThrow(EntityNotFoundException::new);
50+
51+
mv.addObject("view", ArticleView.of(currentArticle.getArticleRevision(), mainSlug));
52+
mv.addObject("revisions", articleRevisionRepository.findHistory(nodeId, pageable));
53+
54+
return mv;
55+
}
56+
57+
@GetMapping("/wiki/{nodeId}/revisions/{revision}/view")
58+
public ModelAndView show(@PathVariable final Integer nodeId, @PathVariable final Integer revision, final ModelAndView mv) {
59+
mv.setViewName("layouts/bare");
60+
mv.addObject("title", "Die Linuxspiele-Seite für Linuxspieler");
61+
mv.addObject(WebDefines.DEFAULT_VIEW_ATTRIBUTE_NAME, "sites/revisions/show");
62+
63+
64+
65+
return mv;
66+
}
67+
68+
}

src/main/java/de/holarse/web/controller/WikiController.java

+8-4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
import de.holarse.queues.commands.SearchRefresh;
1212
import de.holarse.web.controller.commands.ArticleForm;
1313
import de.holarse.web.defines.WebDefines;
14+
15+
import static de.holarse.web.defines.WebDefines.REVISION_DEFAULT_PAGE_SIZE;
1416
import static de.holarse.web.defines.WebDefines.WIKI_ARTICLES_DEFAULT_PAGE_SIZE;
1517
import de.holarse.web.renderer.Renderer;
1618
import de.holarse.web.services.AttachmentService;
@@ -26,7 +28,9 @@
2628
import org.slf4j.Logger;
2729
import org.slf4j.LoggerFactory;
2830
import org.springframework.beans.factory.annotation.Autowired;
31+
import org.springframework.data.domain.Page;
2932
import org.springframework.data.domain.Pageable;
33+
import org.springframework.data.domain.Sort;
3034
import org.springframework.data.web.PageableDefault;
3135
import org.springframework.jms.core.JmsTemplate;
3236
import org.springframework.stereotype.Controller;
@@ -105,7 +109,7 @@ public ModelAndView show(@PathVariable("slug") final String slug, final ModelAnd
105109
final ArticleRevision articleRevision = article.getArticleRevision();
106110
final Set<Tag> tags = article.getTags();
107111
final List<TagGroup> relevantTagGroups = tags.stream().map(t -> t.getTagGroup()).toList();
108-
//final NodeSlug mainSlug = nodeSlugRepository.findMainSlug(article.getNodeId()).orElseThrow(EntityNotFoundException::new);
112+
final NodeSlug mainSlug = nodeSlugRepository.findMainSlug(articleRevision.getNodeId(), NodeType.article).orElseThrow(EntityNotFoundException::new);
109113

110114
// TODO
111115
// if (article.getNodeStatus().isDeleted() || !article.getNodeStatus().isPublished()) {
@@ -126,7 +130,7 @@ public ModelAndView show(@PathVariable("slug") final String slug, final ModelAnd
126130
final List<Attachment> videos = attachmentService.getAttachments(article, attachmentGroupRepository.findByCode(AttachmentGroupType.video.name()));
127131

128132
// View zusammenstellen
129-
final ArticleView view = ArticleView.of(articleRevision);
133+
final ArticleView view = ArticleView.of(articleRevision, mainSlug);
130134
view.setNodeId(article.getNodeId());
131135
view.setTagList(tags.stream().map(TagView::of).sorted(Comparator.comparingInt(TagView::getWeight).reversed().thenComparing(TagView::getUseCount).reversed().thenComparing(TagView::getName)).toList());
132136
view.setContent(renderer.render(view.getContent(), null));
@@ -188,7 +192,7 @@ public ModelAndView edit(@PathVariable final Integer nodeId, final ModelAndView
188192

189193
@Transactional
190194
@PostMapping("{nodeId}")
191-
public ModelAndView update(@PathVariable("nodeId") final int nodeId, @ModelAttribute("form") final ArticleForm form, final ModelAndView mv, final Principal principal) {
195+
public ModelAndView update(@PathVariable final int nodeId, @ModelAttribute("form") final ArticleForm form, final ModelAndView mv, final Principal principal) {
192196
logger.debug("Updating by form {}", form);
193197

194198
final Article article = articleRepository.findByNodeId(nodeId).orElseThrow(EntityNotFoundException::new);
@@ -262,7 +266,7 @@ public ModelAndView update(@PathVariable("nodeId") final int nodeId, @ModelAttri
262266
logger.debug("Should redirect to {}", nodeSlug.getName());
263267
return new ModelAndView(String.format("redirect:%s", nodeSlug.getName()));
264268
}
265-
269+
266270
protected Attachment createOrUpdate(final Integer nodeId, final Attachment formAttachment) {
267271
Attachment dbAttachment;
268272
if (formAttachment.getId() == null) {

src/main/java/de/holarse/web/defines/WebDefines.java

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ public class WebDefines {
77
public static final int DEFAULT_LIST_SIZE = 25;
88
public static final int ADMIN_USERS_DEFAULT_PAGE_SIZE = DEFAULT_LIST_SIZE;
99
public static final int WIKI_ARTICLES_DEFAULT_PAGE_SIZE = 50;
10+
public static final int REVISION_DEFAULT_PAGE_SIZE = 10;
1011

1112
public static final String TAG_DELIMITER = "@@@";
1213

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<section class="g-pt-50 g-pb-90">
2+
<div class="container">
3+
<div class="row">
4+
Revisionen von
5+
<h3 class="h4 g-mb-15">
6+
<a class="u-link-v5 g-color-gray-dark-v1 g-color-primary--hover" href="#" data-th-href="@{view.url}" data-th-text="${view.title1}"></a>
7+
</h3>
8+
</div>
9+
<div class="row">
10+
11+
<div class="table-responsive">
12+
<table class="table table-striped">
13+
<thead>
14+
<tr>
15+
<th>Revision</th>
16+
<th>Datum</th>
17+
<th>Autor</th>
18+
<th>Changelog</th>
19+
<th colspan="2">
20+
<a href="#!" class="btn btn-xs u-btn-primary g-mr-10 g-mb-15">
21+
<i class="fa fa-exchange g-mr-3"></i>
22+
Unterschiede anzeigen
23+
</a>
24+
</th>
25+
<th>Operationen</th>
26+
</tr>
27+
</thead>
28+
<tbody>
29+
<tr data-th-each="revision : ${revisions}">
30+
<td><a href="#" data-th-href="@{/wiki/{nodeId}/revisions/{revisionId}/view(nodeId=${revision.nodeId},revisionId=${revision.revision})}" data-th-text="${revision.revision}"></a></td>
31+
<td data-th-text="${revision.created}"></td>
32+
<td data-th-text="${revision.author?.login}"></td>
33+
<td data-th-text="${revision.changelog}"></td>
34+
<td>
35+
<label class="form-check-inline u-check">
36+
<input class="g-hidden-xs-up g-pos-abs g-top-0 g-left-0" name="revisionLeftGroup" type="radio" checked="">
37+
<div class="u-check-icon-font g-absolute-centered--y g-left-0">
38+
<i class="fa" data-check-icon="" data-uncheck-icon=""></i>
39+
</div>
40+
</label>
41+
</td>
42+
<td>
43+
<label class="form-check-inline u-check">
44+
<input class="g-hidden-xs-up g-pos-abs g-top-0 g-left-0" name="revisionRightGroup" type="radio" checked="">
45+
<div class="u-check-icon-font g-absolute-centered--y g-left-0">
46+
<i class="fa" data-check-icon="" data-uncheck-icon=""></i>
47+
</div>
48+
</label>
49+
</td>
50+
<td colspan="2">
51+
<a href="#!" class="btn btn-xs u-btn-primary g-mr-10 g-mb-15">
52+
<i class="fa fa-mail-reply g-mr-3"></i>
53+
Zurücksetzen
54+
</a>
55+
<a href="#!" class="btn btn-xs u-btn-primary g-mr-10 g-mb-15">
56+
<i class="fa fa-trash g-mr-3"></i>
57+
Löschen
58+
</a>
59+
</td>
60+
</tr>
61+
</tbody>
62+
</table>
63+
64+
</div>
65+
</div>
66+
</section>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<section class="g-pt-50 g-pb-90">
2+
<div class="container">
3+
Revision
4+
</div>
5+
</section>

src/main/webapp/WEB-INF/templates/sites/wiki/show.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ <h4 class="g-font-weight-200" data-th-text="${altTitle}"></h4>
1717
<div class="col-sm-2">
1818
<ul class="list-group list-group-horizontal">
1919
<a href="?edit" class="list-group-item flex-fill">bearbeiten</a>
20-
<a href="#" class="list-group-item flex-fill">Änderungen</a>
20+
<a href="#" class="list-group-item flex-fill" data-th-href="@{/wiki/{nodeId}/revisions(nodeId=${view.nodeId})}">Änderungen</a>
2121
<a href="#" class="list-group-item flex-fill">Statistik</a>
2222
</ul>
2323

0 commit comments

Comments
 (0)