Skip to content

Commit 304100d

Browse files
committed
Post editing
1 parent 4115d8d commit 304100d

13 files changed

Lines changed: 440 additions & 64 deletions

File tree

src/main/java/alexp/blog/controller/PostsController.java

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import alexp.blog.model.Comment;
44
import alexp.blog.model.Post;
5+
import alexp.blog.model.PostEditDto;
56
import alexp.blog.service.PostService;
67
import alexp.blog.service.UserService;
78
import org.springframework.beans.factory.annotation.Autowired;
@@ -32,13 +33,13 @@ public String showPostsList(@RequestParam(value = "page", defaultValue = "0") In
3233
}
3334

3435
@RequestMapping(value = "/tag", method = RequestMethod.GET)
35-
public @ResponseBody String searchByTag(@RequestParam(value = "name") String tagName, ModelMap model) {
36+
public @ResponseBody String searchByTag(@RequestParam("name") String tagName, ModelMap model) {
3637

3738
return "search by tag: TODO";
3839
}
3940

4041
@RequestMapping(value = "/post", method = RequestMethod.GET)
41-
public String showPost(@RequestParam(value = "id") Long postId, ModelMap model) {
42+
public String showPost(@RequestParam("id") Long postId, ModelMap model) {
4243
Post post = postService.getPost(postId);
4344

4445
if (post == null)
@@ -56,33 +57,56 @@ public String showPost(@RequestParam(value = "id") Long postId, ModelMap model)
5657
@PreAuthorize("hasRole('ROLE_ADMIN')")
5758
@RequestMapping(value = "/post/create", method = RequestMethod.GET)
5859
public String showCreatePostForm(ModelMap model) {
59-
model.addAttribute("post", new Post());
60+
model.addAttribute("post", new PostEditDto());
6061

6162
model.addAttribute("edit", false);
6263

63-
return "createpost";
64+
return "editpost";
6465
}
6566

6667
@PreAuthorize("hasRole('ROLE_ADMIN')")
6768
@RequestMapping(value = "/post/create", method = RequestMethod.POST)
68-
public String createPost(ModelMap model, @Valid @ModelAttribute(value = "post") Post post, BindingResult result,
69-
@RequestParam(value = "tagstext", defaultValue = "") String tagstext) {
69+
public String createPost(ModelMap model, @Valid @ModelAttribute("post") PostEditDto post, BindingResult result) {
7070
if (result.hasErrors()) {
7171
model.addAttribute("edit", false);
7272

73-
return "createpost";
73+
return "editpost";
7474
}
7575

76-
postService.saveNewPost(post, tagstext);
76+
postService.saveNewPost(post);
7777

7878
return "redirect:/posts";
7979
}
8080

8181
@PreAuthorize("hasRole('ROLE_ADMIN')")
8282
@RequestMapping(value = "/post/edit", method = RequestMethod.GET)
83-
public String showEditPostForm(ModelMap model) {
83+
public String showEditPostForm(@RequestParam("id") Long postId, ModelMap model) {
84+
PostEditDto post = postService.getEditablePost(postId);
85+
86+
if (post == null)
87+
throw new ResourceNotFoundException();
88+
89+
model.addAttribute("post", post);
90+
8491
model.addAttribute("edit", true);
8592

86-
return "createpost";
93+
return "editpost";
94+
}
95+
96+
@PreAuthorize("hasRole('ROLE_ADMIN')")
97+
@RequestMapping(value = "/post/edit", method = RequestMethod.POST)
98+
public String showEditPostForm(ModelMap model, @Valid @ModelAttribute("post") PostEditDto post, BindingResult result,
99+
@RequestParam("id") Long postId) {
100+
post.setId(postId);
101+
102+
if (result.hasErrors()) {
103+
model.addAttribute("edit", true);
104+
105+
return "editpost";
106+
}
107+
108+
postService.updatePost(post);
109+
110+
return "redirect:/post?id=" + postId;
87111
}
88112
}

src/main/java/alexp/blog/model/Post.java

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,28 +21,20 @@ public class Post {
2121
private Long Id;
2222

2323
@Column(length = 250, nullable = false)
24-
// haven't figured out how to specify messages for Size.List in the messages file
25-
@Size.List({
26-
@Size(min = 3, message = "Title too short"),
27-
@Size(max = 250, message = "Title too long")
28-
})
29-
@NotBlank
3024
private String title;
3125

3226
@Lob
3327
private String shortTextPart;
3428

3529
@Lob
3630
@Column(nullable = false)
37-
@NotBlank
38-
@Size(min = 50)
3931
private String fullPostText;
4032

4133
@Column(columnDefinition="DATETIME", nullable = false)
4234
@Temporal(TemporalType.TIMESTAMP)
4335
private Date dateTime;
4436

45-
@ManyToMany(fetch = FetchType.EAGER)
37+
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
4638
@JoinTable(name = "posts_tags",
4739
joinColumns = @JoinColumn(name = "post_id", referencedColumnName = "id"),
4840
inverseJoinColumns = @JoinColumn(name = "tag_id", referencedColumnName = "id"))
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package alexp.blog.model;
2+
3+
import org.hibernate.validator.constraints.NotBlank;
4+
5+
import javax.validation.constraints.Size;
6+
7+
public class PostEditDto {
8+
9+
private Long Id = null;
10+
11+
// haven't figured out how to specify messages for Size.List in the messages file
12+
@Size.List({
13+
@Size(min = 3, message = "Title too short"),
14+
@Size(max = 250, message = "Title too long")
15+
})
16+
@NotBlank
17+
private String title;
18+
19+
@NotBlank
20+
@Size(min = 50)
21+
private String text;
22+
23+
@NotBlank
24+
private String tags = "";
25+
26+
public Long getId() {
27+
return Id;
28+
}
29+
30+
public void setId(Long id) {
31+
Id = id;
32+
}
33+
34+
public String getTitle() {
35+
return title;
36+
}
37+
38+
public void setTitle(String title) {
39+
this.title = title;
40+
}
41+
42+
public String getText() {
43+
return text;
44+
}
45+
46+
public void setText(String text) {
47+
this.text = text;
48+
}
49+
50+
public String getTags() {
51+
return tags;
52+
}
53+
54+
public void setTags(String tags) {
55+
this.tags = tags;
56+
}
57+
}

src/main/java/alexp/blog/model/Tag.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ public class Tag {
1818
@ManyToMany(mappedBy = "tags")
1919
private Collection<Post> posts = new ArrayList<>();
2020

21+
public Tag() {
22+
}
23+
24+
public Tag(String name) {
25+
this.name = name;
26+
}
27+
2128
public Long getId() {
2229
return Id;
2330
}
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package alexp.blog.service;
22

33
import alexp.blog.model.Post;
4+
import alexp.blog.model.PostEditDto;
45
import org.springframework.data.domain.Page;
56

67
public interface PostService {
@@ -9,5 +10,9 @@ public interface PostService {
910

1011
Post getPost(Long id);
1112

12-
void saveNewPost(Post post, String tagstext);
13+
PostEditDto getEditablePost(Long id);
14+
15+
Post saveNewPost(PostEditDto postEditDto);
16+
17+
Post updatePost(PostEditDto postEditDto);
1318
}

src/main/java/alexp/blog/service/PostServiceImpl.java

Lines changed: 65 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package alexp.blog.service;
22

33
import alexp.blog.model.Post;
4+
import alexp.blog.model.PostEditDto;
45
import alexp.blog.model.Tag;
56
import alexp.blog.repository.PostRepository;
67
import alexp.blog.repository.TagRepository;
@@ -9,8 +10,9 @@
910
import org.springframework.data.domain.PageRequest;
1011
import org.springframework.data.domain.Sort;
1112
import org.springframework.stereotype.Service;
12-
13+
import java.util.Arrays;
1314
import java.util.Date;
15+
import java.util.stream.Collectors;
1416

1517
@Service("postService")
1618
public class PostServiceImpl implements PostService
@@ -32,28 +34,79 @@ public Post getPost(Long id) {
3234
}
3335

3436
@Override
35-
public void saveNewPost(Post post, String tagstext) {
36-
int cutInd = post.getFullPostText().indexOf(Post.shortPartSeparator());
37+
public PostEditDto getEditablePost(Long id) {
38+
Post post = getPost(id);
39+
40+
if (post == null)
41+
return null;
42+
43+
return convertToPostEditDto(post);
44+
}
45+
46+
@Override
47+
public Post saveNewPost(PostEditDto postEditDto) {
48+
Post post = new Post();
49+
50+
fillPost(post, postEditDto);
51+
52+
post.setDateTime(new Date());
53+
54+
postRepository.saveAndFlush(post);
55+
56+
return post;
57+
}
58+
59+
@Override
60+
public Post updatePost(PostEditDto postEditDto) {
61+
if (postEditDto.getId() == null)
62+
throw new IllegalArgumentException("cannot update without id");
63+
64+
Post post = getPost(postEditDto.getId());
65+
66+
fillPost(post, postEditDto);
67+
68+
postRepository.saveAndFlush(post);
69+
70+
return post;
71+
}
72+
73+
private PostEditDto convertToPostEditDto(Post post) {
74+
PostEditDto postEditDto = new PostEditDto();
75+
76+
postEditDto.setId(post.getId());
77+
postEditDto.setText(post.getFullPostText());
78+
postEditDto.setTitle(post.getTitle());
79+
80+
postEditDto.setTags(post.getTags().stream().map(Tag::getName).collect(Collectors.joining(", ")));
81+
82+
return postEditDto;
83+
}
84+
85+
private void fillPost(Post post, PostEditDto postEditDto) {
86+
post.setId(postEditDto.getId());
87+
post.setTitle(postEditDto.getTitle());
88+
post.setFullPostText(postEditDto.getText());
89+
90+
int cutInd = postEditDto.getText().indexOf(Post.shortPartSeparator());
3791
if (cutInd > 0) {
38-
post.setShortTextPart(post.getFullPostText().substring(0, cutInd));
92+
post.setShortTextPart(postEditDto.getText().substring(0, cutInd));
93+
}
94+
else {
95+
post.setShortTextPart(null);
3996
}
4097

41-
post.setDateTime(new Date());
98+
post.getTags().clear();
4299

43-
String[] tags = tagstext.split(",");
100+
String[] tags = Arrays.stream(postEditDto.getTags().split(",")).map(String::trim).toArray(String[]::new);
44101

45102
for (String tagname: tags) {
46-
Tag tag = tagRepository.findByNameIgnoreCase(tagname.trim());
103+
Tag tag = tagRepository.findByNameIgnoreCase(tagname);
47104

48105
if (tag == null) {
49-
tag = new Tag();
50-
tag.setName(tagname.trim());
51-
tagRepository.save(tag);
106+
tag = new Tag(tagname);
52107
}
53108

54109
post.getTags().add(tag);
55110
}
56-
57-
postRepository.saveAndFlush(post);
58111
}
59112
}

src/main/resources/Messages.properties

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ Registered.user.email=Email already registered. Have you already registered? Con
66
NotBlank.user.password=Enter password
77

88
NotBlank.post.title=Enter title
9-
NotBlank.post.fullPostText=Text cannot be empty
10-
Size.post.fullPostText=Too short text
9+
NotBlank.post.text=Text cannot be empty
10+
NotBlank.post.tags=Add at least one tag
11+
Size.post.text=Too short text
1112

1213
NotBlank.comment.commentText=Empty comments not allowed

src/main/webapp/WEB-INF/templates/createpost.html renamed to src/main/webapp/WEB-INF/templates/editpost.html

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
});
6161

6262
$('#insertSeparator').click(function(){
63-
$textarea = $('#wmd-input');
63+
var $textarea = $('#wmd-input');
6464
$textarea.insertAtCaret('===cut===');
6565
});
6666

@@ -70,10 +70,10 @@
7070
required: true,
7171
minlength: 3
7272
},
73-
tagstext: {
73+
tags: {
7474
required: true
7575
},
76-
fullPostText: {
76+
text: {
7777
required: true,
7878
minlength: 50
7979
}
@@ -83,9 +83,9 @@
8383
</script>
8484

8585
<div class="col-sm-8">
86-
<h2>Create post</h2>
86+
<h2 th:text="${edit} ? 'Edit post' : 'Create post'"></h2>
8787

88-
<form th:action="@{/post/create}" th:object="${post}" method="post" id="postForm">
88+
<form th:action="${edit} ? @{/post/edit(id=${post.id})} : @{/post/create}" th:object="${post}" method="post" id="postForm">
8989
<div th:if="${#fields.hasErrors('*')}">
9090
<ul class="list-no-indent">
9191
<li class="error-line" th:each="err : ${#fields.errors('*')}" th:text="${err}"></li>
@@ -99,16 +99,16 @@ <h2>Create post</h2>
9999

100100
<div class="form-group wmd-panel">
101101
<div id="wmd-button-bar"></div>
102-
<textarea class="wmd-input" id="wmd-input" th:field="*{fullPostText}"></textarea>
102+
<textarea class="wmd-input" id="wmd-input" th:field="*{text}"></textarea>
103103
<div id="wmd-preview" class="wmd-panel wmd-preview"></div>
104104
</div>
105105

106106
<div class="form-group">
107107
<label for="tags">Tags:</label>
108-
<input type="text" class="form-control" id="tags" placeholder="c++, php" name="tagstext"/>
108+
<input type="text" class="form-control" id="tags" th:field="*{tags}" placeholder="c++, php"/>
109109
</div>
110110

111-
<button type="submit" class="btn btn-default">Submit</button>
111+
<button type="submit" class="btn btn-default" th:text="${edit} ? 'Save' : 'Submit'"></button>
112112

113113
</form>
114114
</div>

src/main/webapp/WEB-INF/templates/post.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ <h2 class="post-title" th:text="${post.title}"></h2>
123123
</div>
124124

125125
<div class="post-content" th:utext="${post.fullPostTextHtml()}"></div>
126+
127+
<div class="post-actions">
128+
<a sec:authorize="hasRole('ROLE_ADMIN')" th:href="@{/post/edit(id=${post.id})}">edit</a>
129+
</div>
126130
</div>
127131

128132
<div class="comments">

0 commit comments

Comments
 (0)