1 /*
2 * Copyright (C) 2009 Emweb bv, Herent, Belgium.
3 *
4 * See the LICENSE file for terms of use.
5 */
6
7 #include "CommentView.h"
8
9 #include "../model/BlogSession.h"
10 #include "../model/Comment.h"
11 #include "../model/User.h"
12
13 #include <Wt/WContainerWidget.h>
14 #include <Wt/WPushButton.h>
15 #include <Wt/WTemplate.h>
16 #include <Wt/WText.h>
17 #include <Wt/WTextArea.h>
18
19 namespace dbo = Wt::Dbo;
20
CommentView(BlogSession & session,dbo::ptr<Comment> comment)21 CommentView::CommentView(BlogSession& session, dbo::ptr<Comment> comment)
22 : session_(session),
23 comment_(comment)
24 {
25 comment_ = comment;
26
27 renderView();
28 }
29
CommentView(BlogSession & session,long long parentId)30 CommentView::CommentView(BlogSession& session, long long parentId)
31 : session_(session)
32 {
33 dbo::ptr<Comment> parent = session_.load<Comment>(parentId);
34
35 comment_ = std::make_unique<Comment>();
36 comment_.modify()->parent = parent;
37 comment_.modify()->post = parent->post;
38
39 edit();
40 }
41
isNew()42 bool CommentView::isNew() const
43 {
44 return comment_.id() == -1;
45 }
46
edit()47 void CommentView::edit()
48 {
49 clear();
50
51 dbo::Transaction t(session_);
52
53 setTemplateText(tr("blog-edit-comment"));
54
55 auto editArea = std::make_unique<Wt::WTextArea>();
56 editArea_ = editArea.get();
57 editArea_->setText(comment_->textSrc());
58 editArea_->setFocus();
59
60 auto save = std::make_unique<Wt::WPushButton>(tr("save"));
61 save->clicked().connect(this, &CommentView::save);
62
63 auto cancel = std::make_unique<Wt::WPushButton>(tr("cancel"));
64 cancel->clicked().connect(this, &CommentView::cancel);
65
66 bindWidget("area", std::move(editArea));
67 bindWidget("save", std::move(save));
68 bindWidget("cancel", std::move(cancel));
69
70 t.commit();
71 }
72
cancel()73 void CommentView::cancel()
74 {
75 if (isNew())
76 removeFromParent();
77 else {
78 dbo::Transaction t(session_);
79 renderView();
80 t.commit();
81 }
82 }
83
renderTemplate(std::ostream & result)84 void CommentView::renderTemplate(std::ostream& result)
85 {
86 dbo::Transaction t(session_);
87
88 WTemplate::renderTemplate(result);
89
90 comment_.purge();
91
92 t.commit();
93 }
94
resolveString(const std::string & varName,const std::vector<Wt::WString> & args,std::ostream & result)95 void CommentView::resolveString(const std::string& varName,
96 const std::vector<Wt::WString>& args,
97 std::ostream& result)
98 {
99 if (varName == "author")
100 format(result, comment_->author ? comment_->author->name : "anonymous");
101 else if (varName == "date")
102 format(result, comment_->date.timeTo(Wt::WDateTime::currentDateTime())
103 + " ago");
104 else if (varName == "contents")
105 format(result, comment_->textHtml(), Wt::TextFormat::XHTML);
106 else
107 WTemplate::resolveString(varName, args, result);
108 }
109
renderView()110 void CommentView::renderView()
111 {
112 clear();
113
114 bool isRootComment = !comment_->parent;
115 setTemplateText(isRootComment ? tr("blog-root-comment")
116 : tr("blog-comment"));
117
118 bindString("collapse-expand", Wt::WString::Empty); // NYI
119
120 auto replyText
121 = std::make_unique<Wt::WText>(isRootComment ? tr("comment-add")
122 : tr("comment-reply"));
123 replyText->setStyleClass("link");
124 replyText->clicked().connect(this, &CommentView::reply);
125 bindWidget("reply", std::move(replyText));
126
127 bool mayEdit = session_.user()
128 && (comment_->author == session_.user()
129 || session_.user()->role == User::Admin);
130
131 if (mayEdit) {
132 auto editText
133 = std::make_unique<Wt::WText>(tr("comment-edit"));
134 editText->setStyleClass("link");
135 editText->clicked().connect(this, &CommentView::edit);
136 bindWidget("edit", std::move(editText));
137 } else
138 bindString("edit", Wt::WString::Empty);
139
140 bool mayDelete
141 = (session_.user() && session_.user() == comment_->author)
142 || session_.user() == comment_->post->author;
143
144 if (mayDelete) {
145 auto deleteText
146 = std::make_unique<Wt::WText>(tr("comment-delete"));
147 deleteText->setStyleClass("link");
148 deleteText->clicked().connect(this, &CommentView::rm);
149 bindWidget("delete", std::move(deleteText));
150 } else
151 bindString("delete", Wt::WString::Empty);
152
153 typedef std::vector< dbo::ptr<Comment> > CommentVector;
154 CommentVector comments;
155 {
156 dbo::collection<dbo::ptr<Comment> > cmts
157 = comment_->children.find().orderBy("date");
158 comments.insert(comments.end(), cmts.begin(), cmts.end());
159 }
160
161 auto children
162 = std::make_unique<Wt::WContainerWidget>();
163 for (int i = (int)comments.size() - 1; i >= 0; --i)
164 children->addWidget(std::make_unique<CommentView>(session_, comments[i]));
165
166 bindWidget("children", std::move(children));
167 }
168
save()169 void CommentView::save()
170 {
171 dbo::Transaction t(session_);
172
173 bool isNew = comment_.id() == -1;
174
175 Comment *comment = comment_.modify();
176
177 comment->setText(editArea_->text());
178
179 if (isNew) {
180 session_.add(comment_);
181 comment->date = Wt::WDateTime::currentDateTime();
182 comment->author = session_.user();
183 session_.commentsChanged().emit(comment_);
184 }
185
186 renderView();
187
188 t.commit();
189 }
190
reply()191 void CommentView::reply()
192 {
193 dbo::Transaction t(session_);
194
195 Wt::WContainerWidget *c = resolve<Wt::WContainerWidget *>("children");
196 c->insertWidget(0, std::make_unique<CommentView>(session_, comment_.id()));
197
198 t.commit();
199 }
200
rm()201 void CommentView::rm()
202 {
203 dbo::Transaction t(session_);
204
205 comment_.modify()->setDeleted();
206 renderView();
207
208 t.commit();
209 }
210