mirror of
https://github.com/lxsang/antd-web-apps
synced 2025-07-25 01:59:47 +02:00
use quicktalk as comment API
This commit is contained in:
122
talk/assets/quicktalk.css
Normal file
122
talk/assets/quicktalk.css
Normal file
@ -0,0 +1,122 @@
|
||||
.quick-talk-compose {
|
||||
display: block;
|
||||
border: 1px solid #e5e5e5;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.quick-talk-compose input {
|
||||
display: block;
|
||||
width: 100%;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
font-style: italic;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
font-size: 13px;
|
||||
color: #878887;
|
||||
}
|
||||
|
||||
.quick-talk-compose textarea {
|
||||
display: block;
|
||||
width: 100%;
|
||||
min-height: 100px;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
outline: none;
|
||||
margin: 0;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
font-size: 13px;
|
||||
color: #2c2c2c;
|
||||
}
|
||||
|
||||
.quick-talk-compose .quick-talk-preview {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.quick-talk-compose .quick-talk-compose-footer {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.quick-talk-compose .quick-talk-compose-footer div {
|
||||
display: block;
|
||||
flex: 1;
|
||||
color: orangered;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.quick-talk-compose .quick-talk-compose-footer button,
|
||||
.quick-talk-compose-button {
|
||||
color: white;
|
||||
background-color: steelblue;
|
||||
padding: 5px;
|
||||
font-weight: bold;
|
||||
border: 1px solid #e5e5e5;
|
||||
outline: 0;
|
||||
border-radius: 5px;
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
.quick-talk-compose-button {
|
||||
margin-bottom: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.quick-talk-comment-thread {
|
||||
display: block;
|
||||
}
|
||||
.quick-talk-comment-thread .quick-talk-comment {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.quick-talk-comment-thread .quick-talk-sub-comment {
|
||||
margin-top: 10px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.quick-talk-comment-thread .quick-talk-comment-header {
|
||||
border-top: 1px solid #e5e5e5;
|
||||
display: flex;
|
||||
padding-top: 10px;
|
||||
width: 100%;
|
||||
flex-direction: row;
|
||||
}
|
||||
.quick-talk-comment-thread .quick-talk-comment-footer {
|
||||
display: block;
|
||||
margin: 0;
|
||||
margin-left: 20px;
|
||||
margin-bottom: 10px;
|
||||
padding: 0;
|
||||
}
|
||||
.quick-talk-comment-thread .quick-talk-comment-footer span {
|
||||
display: block;
|
||||
color: steelblue;
|
||||
cursor: pointer;
|
||||
/* text-align: right; */
|
||||
width: 100%;
|
||||
}
|
||||
.quick-talk-comment-thread .quick-talk-comment-footer span:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.quick-talk-comment-thread .quick-talk-comment-user {
|
||||
font-weight: bold;
|
||||
color: steelblue;
|
||||
padding-left: 3px;
|
||||
padding-right: 3px;
|
||||
padding-top: 1px;
|
||||
padding-bottom: 1px;
|
||||
border-radius: 5px;
|
||||
background-color: #e1ecf4;
|
||||
}
|
||||
|
||||
.quick-talk-comment-thread .quick-talk-comment-time {
|
||||
font-style: italic;
|
||||
color: steelblue;
|
||||
margin-left: 5px;
|
||||
padding-top: 1px;
|
||||
font-size: 13px;
|
||||
}
|
||||
.quick-talk-comment-thread .quick-talk-comment-content {
|
||||
display: block;
|
||||
margin-left: 20px;
|
||||
color: #2c2c2c;
|
||||
}
|
248
talk/assets/quicktalk.js
Normal file
248
talk/assets/quicktalk.js
Normal file
@ -0,0 +1,248 @@
|
||||
class QuickTalk {
|
||||
constructor(opt) {
|
||||
this.options = opt;
|
||||
if (typeof this.options.target === "string") {
|
||||
this.options.target = document.getElementById(this.options.target);
|
||||
}
|
||||
this.preview_on = false;
|
||||
this.instant_compose = undefined;
|
||||
let editor = document.createElement("div");
|
||||
let compose_button = document.createElement("button");
|
||||
compose_button.setAttribute("class", "quick-talk-compose-button");
|
||||
compose_button.textContent = "Write a comment";
|
||||
this.options.target.appendChild(compose_button);
|
||||
this.options.target.appendChild(editor);
|
||||
let container = this.load_thread(this.options.target);
|
||||
compose_button.addEventListener("click", (event) => {
|
||||
if (this.instant_compose) {
|
||||
this.instant_compose.parentNode.removeChild(this.instant_compose);
|
||||
}
|
||||
this.instant_compose = this.compose(editor, 0, true, (data) => {
|
||||
this.show_comment(container, data, true).scrollIntoView();
|
||||
});
|
||||
});
|
||||
}
|
||||
request(uri, data, callback) {
|
||||
let xhttp = new XMLHttpRequest();
|
||||
xhttp.open("POST", uri, true);
|
||||
xhttp.setRequestHeader("Content-type", "application/json");
|
||||
xhttp.onreadystatechange = () => {
|
||||
if (xhttp.readyState == 4) {
|
||||
if (xhttp.status == 200) {
|
||||
if (callback) {
|
||||
callback(JSON.parse(xhttp.responseText));
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.error(xhttp.statusText);
|
||||
}
|
||||
}
|
||||
};
|
||||
if (data) {
|
||||
xhttp.send(JSON.stringify(data));
|
||||
}
|
||||
else {
|
||||
xhttp.send();
|
||||
}
|
||||
}
|
||||
set_status(type, msg) {
|
||||
if (this.status_el) {
|
||||
this.status_el.innerHTML = type + ": " + msg;
|
||||
}
|
||||
else {
|
||||
console.log(type + ": " + msg);
|
||||
}
|
||||
}
|
||||
clear_status() {
|
||||
this.status_el.innerHTML = "";
|
||||
}
|
||||
info(msg) {
|
||||
this.set_status("INFO", msg);
|
||||
}
|
||||
error(obj) {
|
||||
console.log(obj);
|
||||
this.set_status("ERROR", obj.toString());
|
||||
}
|
||||
compose(at, cid, auto_hide, callback) {
|
||||
let preview = document.createElement("div");
|
||||
preview.setAttribute("class", "quick-talk-preview");
|
||||
preview.style.display = "none";
|
||||
let container = document.createElement("div");
|
||||
container.setAttribute("class", "quick-talk-compose");
|
||||
let name = document.createElement("input");
|
||||
name.value = "Name";
|
||||
name.addEventListener("focus", (event) => {
|
||||
if (name.value == "Name") {
|
||||
name.value = "";
|
||||
}
|
||||
});
|
||||
name.addEventListener("blur", (event) => {
|
||||
if (name.value.trim() == "") {
|
||||
name.value = "Name";
|
||||
}
|
||||
});
|
||||
let email = document.createElement("input");
|
||||
email.value = "Email";
|
||||
email.addEventListener("focus", (event) => {
|
||||
if (email.value == "Email") {
|
||||
email.value = "";
|
||||
}
|
||||
});
|
||||
email.addEventListener("blur", (event) => {
|
||||
if (email.value.trim() == "") {
|
||||
email.value = "Email";
|
||||
}
|
||||
});
|
||||
let ta = document.createElement("textarea");
|
||||
let footer = document.createElement("div");
|
||||
footer.setAttribute("class", "quick-talk-compose-footer");
|
||||
this.status_el = document.createElement("div");
|
||||
let bt_preview = document.createElement("button");
|
||||
bt_preview.textContent = "Preview";
|
||||
bt_preview.addEventListener("click", (event) => {
|
||||
let md = { data: ta.value };
|
||||
if (!this.preview_on && ta.value.trim() != "") {
|
||||
this.request(this.options.api_uri + "/preview", md, (ret) => {
|
||||
if (ret.result) {
|
||||
ta.style.display = "none";
|
||||
preview.innerHTML = ret.result;
|
||||
preview.style.display = "block";
|
||||
bt_preview.textContent = "Edit";
|
||||
this.preview_on = !this.preview_on;
|
||||
}
|
||||
else {
|
||||
this.error(ret.error);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
ta.style.display = "block";
|
||||
preview.style.display = "none";
|
||||
bt_preview.textContent = "Preview";
|
||||
this.preview_on = !this.preview_on;
|
||||
}
|
||||
});
|
||||
let bt_submit = document.createElement("button");
|
||||
bt_submit.textContent = "Send";
|
||||
bt_submit.addEventListener("click", (event) => {
|
||||
this.clear_status();
|
||||
if (name.value.trim() == "" ||
|
||||
name.value.trim() == "Name" ||
|
||||
email.value.trim() == "" ||
|
||||
email.value.trim() == "Email" ||
|
||||
ta.value.trim() == "") {
|
||||
this.info("Please enter all the fields");
|
||||
return;
|
||||
}
|
||||
// check for email
|
||||
let re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
||||
if (!re.test(String(email.value).toLowerCase()))
|
||||
return this.info("Email is not correct");
|
||||
// send the post request
|
||||
let data = {
|
||||
page: {
|
||||
uri: this.options.uri,
|
||||
},
|
||||
comment: {
|
||||
name: name.value,
|
||||
email: email.value,
|
||||
rid: cid,
|
||||
content: ta.value,
|
||||
},
|
||||
};
|
||||
this.request(this.options.api_uri + "/post", data, (ret) => {
|
||||
if (ret.result) {
|
||||
// TODO: more check goes here
|
||||
name.value = "Name";
|
||||
email.value = "Email";
|
||||
ta.value = "";
|
||||
if (auto_hide) {
|
||||
at.removeChild(container);
|
||||
this.instant_compose = undefined;
|
||||
}
|
||||
if (callback) {
|
||||
callback(ret.result);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.error(ret.error);
|
||||
}
|
||||
});
|
||||
});
|
||||
footer.appendChild(this.status_el);
|
||||
footer.appendChild(bt_preview);
|
||||
footer.appendChild(bt_submit);
|
||||
container.appendChild(name);
|
||||
container.appendChild(email);
|
||||
container.appendChild(ta);
|
||||
container.appendChild(preview);
|
||||
container.appendChild(footer);
|
||||
at.appendChild(container);
|
||||
container.scrollIntoView();
|
||||
return container;
|
||||
}
|
||||
load_thread(at) {
|
||||
let container = document.createElement("div");
|
||||
container.setAttribute("class", "quick-talk-comment-thread");
|
||||
at.appendChild(container);
|
||||
this.request(this.options.api_uri, { page: this.options.uri }, (ret) => {
|
||||
if (ret.result) {
|
||||
ret.result.forEach((comment) => {
|
||||
this.show_comment(container, comment, true);
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.error(ret.error);
|
||||
}
|
||||
});
|
||||
return container;
|
||||
}
|
||||
show_comment(at, comment, show_footer) {
|
||||
let container = document.createElement("div");
|
||||
container.setAttribute("class", "quick-talk-comment");
|
||||
let header = document.createElement("div");
|
||||
header.setAttribute("class", "quick-talk-comment-header");
|
||||
let username = document.createElement("span");
|
||||
username.setAttribute("class", "quick-talk-comment-user");
|
||||
let time = document.createElement("span");
|
||||
time.setAttribute("class", "quick-talk-comment-time");
|
||||
let content = document.createElement("div");
|
||||
content.setAttribute("class", "quick-talk-comment-content");
|
||||
username.innerHTML = comment.name;
|
||||
let date = new Date(parseInt(comment.time) * 1000);
|
||||
time.innerHTML = `on ${date.getDate()}/${date.getMonth()}/${date.getFullYear()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}, wrote:`;
|
||||
content.innerHTML = comment.content;
|
||||
header.appendChild(username);
|
||||
header.appendChild(time);
|
||||
container.appendChild(header);
|
||||
container.appendChild(content);
|
||||
let sub_comments = document.createElement("div");
|
||||
sub_comments.setAttribute("class", "quick-talk-sub-comment");
|
||||
if (comment.children && comment.children.length > 0) {
|
||||
comment.children.forEach((cmt) => {
|
||||
this.show_comment(sub_comments, cmt, false);
|
||||
});
|
||||
}
|
||||
container.appendChild(sub_comments);
|
||||
if (show_footer) {
|
||||
let footer = document.createElement("div");
|
||||
footer.setAttribute("class", "quick-talk-comment-footer");
|
||||
let span = document.createElement("span");
|
||||
span.innerText = "Reply";
|
||||
footer.appendChild(span);
|
||||
let editor = document.createElement("div");
|
||||
footer.appendChild(editor);
|
||||
span.addEventListener("click", (event) => {
|
||||
if (this.instant_compose) {
|
||||
this.instant_compose.parentNode.removeChild(this.instant_compose);
|
||||
}
|
||||
this.instant_compose = this.compose(editor, parseInt(comment.id), true, (data) => {
|
||||
this.show_comment(sub_comments, data, false);
|
||||
});
|
||||
});
|
||||
container.appendChild(footer);
|
||||
}
|
||||
at.appendChild(container);
|
||||
return container;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user