api, frontend: allow editing profile information
Closes https://gitlab.com/commento/commento/issues/235
This commit is contained in:
parent
3e1576d494
commit
918a691ba3
@ -1,6 +1,8 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import ()
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
func commenterUpdate(commenterHex string, email string, name string, link string, photo string, provider string) error {
|
func commenterUpdate(commenterHex string, email string, name string, link string, photo string, provider string) error {
|
||||||
if email == "" || name == "" || link == "" || photo == "" || provider == "" {
|
if email == "" || name == "" || link == "" || photo == "" || provider == "" {
|
||||||
@ -27,3 +29,38 @@ func commenterUpdate(commenterHex string, email string, name string, link string
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func commenterUpdateHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
type request struct {
|
||||||
|
CommenterToken *string `json:"commenterToken"`
|
||||||
|
Name *string `json:"name"`
|
||||||
|
Email *string `json:"email"`
|
||||||
|
Link *string `json:"link"`
|
||||||
|
Photo *string `json:"photo"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var x request
|
||||||
|
if err := bodyUnmarshal(r, &x); err != nil {
|
||||||
|
bodyMarshal(w, response{"success": false, "message": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := commenterGetByCommenterToken(*x.CommenterToken)
|
||||||
|
if err != nil {
|
||||||
|
bodyMarshal(w, response{"success": false, "message": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Provider == "commento" {
|
||||||
|
*x.Link = c.Link
|
||||||
|
*x.Photo = c.Photo
|
||||||
|
}
|
||||||
|
*x.Email = c.Email
|
||||||
|
|
||||||
|
if err = commenterUpdate(c.CommenterHex, *x.Email, *x.Name, *x.Link, *x.Photo, c.Provider); err != nil {
|
||||||
|
bodyMarshal(w, response{"success": false, "message": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
bodyMarshal(w, response{"success": true})
|
||||||
|
}
|
||||||
|
@ -27,6 +27,7 @@ func apiRouterInit(router *mux.Router) error {
|
|||||||
router.HandleFunc("/api/commenter/new", commenterNewHandler).Methods("POST")
|
router.HandleFunc("/api/commenter/new", commenterNewHandler).Methods("POST")
|
||||||
router.HandleFunc("/api/commenter/login", commenterLoginHandler).Methods("POST")
|
router.HandleFunc("/api/commenter/login", commenterLoginHandler).Methods("POST")
|
||||||
router.HandleFunc("/api/commenter/self", commenterSelfHandler).Methods("POST")
|
router.HandleFunc("/api/commenter/self", commenterSelfHandler).Methods("POST")
|
||||||
|
router.HandleFunc("/api/commenter/update", commenterUpdateHandler).Methods("POST")
|
||||||
router.HandleFunc("/api/commenter/photo", commenterPhotoHandler).Methods("GET")
|
router.HandleFunc("/api/commenter/photo", commenterPhotoHandler).Methods("GET")
|
||||||
|
|
||||||
router.HandleFunc("/api/forgot", forgotHandler).Methods("POST")
|
router.HandleFunc("/api/forgot", forgotHandler).Methods("POST")
|
||||||
|
@ -102,6 +102,7 @@ func staticRouterInit(router *mux.Router) error {
|
|||||||
"/unsubscribe",
|
"/unsubscribe",
|
||||||
"/dashboard",
|
"/dashboard",
|
||||||
"/logout",
|
"/logout",
|
||||||
|
"/profile",
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, page := range pages {
|
for _, page := range pages {
|
||||||
|
@ -83,6 +83,12 @@ const jsCompileMap = {
|
|||||||
"js/http.js",
|
"js/http.js",
|
||||||
"js/unsubscribe.js",
|
"js/unsubscribe.js",
|
||||||
],
|
],
|
||||||
|
"js/profile.js": [
|
||||||
|
"js/constants.js",
|
||||||
|
"js/utils.js",
|
||||||
|
"js/http.js",
|
||||||
|
"js/profile.js",
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
gulp.task("scss-devel", function (done) {
|
gulp.task("scss-devel", function (done) {
|
||||||
|
@ -246,7 +246,18 @@
|
|||||||
refreshAll();
|
refreshAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
function selfLoad(commenter) {
|
|
||||||
|
function profileEdit() {
|
||||||
|
window.open(origin + "/profile?commenterToken=" + commenterTokenGet(), "_blank");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function notificationSettings(unsubscribeSecretHex) {
|
||||||
|
window.open(origin + "/unsubscribe?unsubscribeSecretHex=" + unsubscribeSecretHex, "_blank");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function selfLoad(commenter, email) {
|
||||||
commenters[commenter.commenterHex] = commenter;
|
commenters[commenter.commenterHex] = commenter;
|
||||||
selfHex = commenter.commenterHex;
|
selfHex = commenter.commenterHex;
|
||||||
|
|
||||||
@ -259,7 +270,9 @@
|
|||||||
name = create("div");
|
name = create("div");
|
||||||
}
|
}
|
||||||
var avatar;
|
var avatar;
|
||||||
var logout = create("div");
|
var notificationSettingsButton = create("div");
|
||||||
|
var profileEditButton = create("div");
|
||||||
|
var logoutButton = create("div");
|
||||||
var color = colorGet(commenter.commenterHex + "-" + commenter.name);
|
var color = colorGet(commenter.commenterHex + "-" + commenter.name);
|
||||||
|
|
||||||
loggedContainer.id = ID_LOGGED_CONTAINER;
|
loggedContainer.id = ID_LOGGED_CONTAINER;
|
||||||
@ -267,12 +280,19 @@
|
|||||||
classAdd(loggedContainer, "logged-container");
|
classAdd(loggedContainer, "logged-container");
|
||||||
classAdd(loggedInAs, "logged-in-as");
|
classAdd(loggedInAs, "logged-in-as");
|
||||||
classAdd(name, "name");
|
classAdd(name, "name");
|
||||||
classAdd(logout, "logout");
|
classAdd(notificationSettingsButton, "profile-button");
|
||||||
|
classAdd(profileEditButton, "profile-button");
|
||||||
|
classAdd(logoutButton, "profile-button");
|
||||||
|
|
||||||
name.innerText = commenter.name;
|
name.innerText = commenter.name;
|
||||||
logout.innerText = "Logout";
|
notificationSettingsButton.innerText = "Notification Settings";
|
||||||
|
profileEditButton.innerText = "Edit Profile";
|
||||||
|
logoutButton.innerText = "Logout";
|
||||||
|
|
||||||
onclick(logout, global.logout);
|
onclick(logoutButton, global.logout);
|
||||||
|
console.log(commenter);
|
||||||
|
onclick(notificationSettingsButton, notificationSettings, email.unsubscribeSecretHex);
|
||||||
|
onclick(profileEditButton, profileEdit);
|
||||||
|
|
||||||
attrSet(loggedContainer, "style", "display: none");
|
attrSet(loggedContainer, "style", "display: none");
|
||||||
if (commenter.link !== "undefined") {
|
if (commenter.link !== "undefined") {
|
||||||
@ -292,7 +312,9 @@
|
|||||||
append(loggedInAs, avatar);
|
append(loggedInAs, avatar);
|
||||||
append(loggedInAs, name);
|
append(loggedInAs, name);
|
||||||
append(loggedContainer, loggedInAs);
|
append(loggedContainer, loggedInAs);
|
||||||
append(loggedContainer, logout);
|
append(loggedContainer, logoutButton);
|
||||||
|
append(loggedContainer, profileEditButton);
|
||||||
|
append(loggedContainer, notificationSettingsButton);
|
||||||
prepend(root, loggedContainer);
|
prepend(root, loggedContainer);
|
||||||
|
|
||||||
isAuthenticated = true;
|
isAuthenticated = true;
|
||||||
@ -318,7 +340,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
selfLoad(resp.commenter);
|
selfLoad(resp.commenter, resp.email);
|
||||||
global.allShow();
|
global.allShow();
|
||||||
|
|
||||||
call(callback);
|
call(callback);
|
||||||
@ -1087,7 +1109,6 @@
|
|||||||
append(card, header);
|
append(card, header);
|
||||||
append(card, contents);
|
append(card, contents);
|
||||||
|
|
||||||
console.log(children);
|
|
||||||
if (comment.deleted && (hideDeleted === "true" || children === null)) {
|
if (comment.deleted && (hideDeleted === "true" || children === null)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1408,7 +1429,6 @@
|
|||||||
|
|
||||||
comment.creationDate = new Date(comment.creationDate);
|
comment.creationDate = new Date(comment.creationDate);
|
||||||
|
|
||||||
console.log(m, parentHex);
|
|
||||||
m[parentHex].push(comment);
|
m[parentHex].push(comment);
|
||||||
commentsMap[comment.commentHex] = {
|
commentsMap[comment.commentHex] = {
|
||||||
"html": comment.html,
|
"html": comment.html,
|
||||||
@ -1730,7 +1750,7 @@
|
|||||||
|
|
||||||
cookieSet("commentoCommenterToken", resp.commenterToken);
|
cookieSet("commentoCommenterToken", resp.commenterToken);
|
||||||
|
|
||||||
selfLoad(resp.commenter);
|
selfLoad(resp.commenter, resp.email);
|
||||||
global.allShow();
|
global.allShow();
|
||||||
|
|
||||||
remove($(ID_LOGIN));
|
remove($(ID_LOGIN));
|
||||||
|
76
frontend/js/profile.js
Normal file
76
frontend/js/profile.js
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
(function (global, document) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
(document);
|
||||||
|
|
||||||
|
// Update the email records.
|
||||||
|
global.update = function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
$(".err").text("");
|
||||||
|
$(".msg").text("");
|
||||||
|
|
||||||
|
var allOk = global.unfilledMark(["#name", "#email"], function(el) {
|
||||||
|
el.css("border-bottom", "1px solid red");
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!allOk) {
|
||||||
|
global.textSet("#err", "Please make sure all fields are filled");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var json = {
|
||||||
|
"commenterToken": global.paramGet("commenterToken"),
|
||||||
|
"name": $("#name").val(),
|
||||||
|
"email": $("#email").val(),
|
||||||
|
"link": $("#link").val(),
|
||||||
|
"photo": $("#photo").val(),
|
||||||
|
};
|
||||||
|
|
||||||
|
global.buttonDisable("#save-button");
|
||||||
|
global.post(global.origin + "/api/commenter/update", json, function(resp) {
|
||||||
|
global.buttonEnable("#save-button");
|
||||||
|
if (!resp.success) {
|
||||||
|
$(".err").text(resp.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$(".msg").text("Successfully updated!");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
global.profilePrefill = function() {
|
||||||
|
$(".err").text("");
|
||||||
|
$(".msg").text("");
|
||||||
|
var json = {
|
||||||
|
"commenterToken": global.paramGet("commenterToken"),
|
||||||
|
};
|
||||||
|
|
||||||
|
global.post(global.origin + "/api/commenter/self", json, function(resp) {
|
||||||
|
$("#loading").hide();
|
||||||
|
$("#form").show();
|
||||||
|
if (!resp.success) {
|
||||||
|
$(".err").text(resp.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$("#name").val(resp.commenter.name);
|
||||||
|
$("#email").val(resp.commenter.email);
|
||||||
|
$("#unsubscribe").attr("href", global.origin + "/unsubscribe?unsubscribeSecretHex=" + resp.email.unsubscribeSecretHex);
|
||||||
|
|
||||||
|
if (resp.commenter.provider === "commento") {
|
||||||
|
$("#link-row").attr("style", "")
|
||||||
|
if (resp.commenter.link !== "undefined") {
|
||||||
|
$("#link").val(resp.commenter.link);
|
||||||
|
}
|
||||||
|
|
||||||
|
$("#photo-row").attr("style", "")
|
||||||
|
$("#photo-subtitle").attr("style", "")
|
||||||
|
if (resp.commenter.photo !== "undefined") {
|
||||||
|
$("#photo").val(resp.commenter.photo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
} (window.commento, document));
|
66
frontend/profile.html
Normal file
66
frontend/profile.html
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta name="viewport" content="user-scalable=no, initial-scale=1.0">
|
||||||
|
<script src="[[[.CdnPrefix]]]/js/jquery.js"></script>
|
||||||
|
<script src="[[[.CdnPrefix]]]/js/profile.js"></script>
|
||||||
|
<link rel="icon" href="[[[.CdnPrefix]]]/images/120x120.png">
|
||||||
|
<link rel="stylesheet" href="[[[.CdnPrefix]]]/css/auth.css">
|
||||||
|
<title>Commento: Edit Profile</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<div class="navbar">
|
||||||
|
<a href="[[[.Origin]]]/" class="navbar-item navbar-logo-text"><img src="[[[.CdnPrefix]]]/images/logo.svg" class="navbar-logo">Commento</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
window.onload = function() {
|
||||||
|
window.commento.profilePrefill();
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="auth-form-container">
|
||||||
|
<div class="auth-form">
|
||||||
|
<div id="loading">
|
||||||
|
Loading...
|
||||||
|
</div>
|
||||||
|
<form onsubmit="window.commento.update(event)" id="form" style="display: none">
|
||||||
|
<div class="form-title">
|
||||||
|
Edit Profile
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="label">Name</div>
|
||||||
|
<input class="input" type="text" name="name" id="name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row no-margin-bottom-row">
|
||||||
|
<div class="label">Email Address</div>
|
||||||
|
<input class="input" type="text" name="email" id="email" placeholder="example@example.com" disabled>
|
||||||
|
</div>
|
||||||
|
<div class="small-subtitle">
|
||||||
|
Since your identity is directly tied to your email address, changing your email address is not possible. <a href="" id="unsubscribe">Want to change your notification settings?</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="link-row" class="row" style="display: none">
|
||||||
|
<div class="label">Website</div>
|
||||||
|
<input class="input" type="text" name="link" id="link" placeholder="https://example.com">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="photo-row" class="row no-margin-bottom-row" style="display: none">
|
||||||
|
<div class="label">Photo</div>
|
||||||
|
<input class="input" type="text" name="photo" id="photo" placeholder="https://i.imgur.com/BCKlYFQ.jpg">
|
||||||
|
</div>
|
||||||
|
<div class="small-subtitle" style="display: none" id="photo-subtitle">
|
||||||
|
Use an external image hosting service such as <a href="https://imgur.com" rel="nofollow">Imgur</a> and enter the direct link to the image here. Changes to your profile photo may take a few hours to reflect.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="err" id="err"></div>
|
||||||
|
<div class="msg" id="msg"></div>
|
||||||
|
|
||||||
|
<button id="button" class="button" type="submit">Update Profile</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
[[[.Footer]]]
|
||||||
|
</html>
|
@ -36,11 +36,17 @@ body {
|
|||||||
padding-bottom: 24px;
|
padding-bottom: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.row {
|
.small-subtitle {
|
||||||
padding-left: 8px;
|
font-size: 12px;
|
||||||
padding-right: 8px;
|
color: $gray-6;
|
||||||
margin-bottom: 20px;
|
padding: 0px 12px 20px 12px;
|
||||||
border-bottom: 1px solid $gray-1;
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
padding-left: 8px;
|
||||||
|
padding-right: 8px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
border-bottom: 1px solid $gray-1;
|
||||||
|
|
||||||
input[type=text],
|
input[type=text],
|
||||||
input[type=password] {
|
input[type=password] {
|
||||||
@ -74,6 +80,10 @@ body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.no-margin-bottom-row {
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
@extend .shadow;
|
@extend .shadow;
|
||||||
border: 1px solid $blue-6;
|
border: 1px solid $blue-6;
|
||||||
|
@ -21,12 +21,12 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
height: 38px;
|
height: 38px;
|
||||||
|
|
||||||
.commento-logout {
|
.commento-profile-button {
|
||||||
|
float: right;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: absolute;
|
color: $gray-6;
|
||||||
top: 6px;
|
margin: 6px 12px;
|
||||||
right: 16px;
|
font-size: 13px;
|
||||||
color: $gray-5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.commento-logged-in-as {
|
.commento-logged-in-as {
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<script src="[[[.CdnPrefix]]]/js/unsubscribe.js"></script>
|
<script src="[[[.CdnPrefix]]]/js/unsubscribe.js"></script>
|
||||||
<link rel="icon" href="[[[.CdnPrefix]]]/images/120x120.png">
|
<link rel="icon" href="[[[.CdnPrefix]]]/images/120x120.png">
|
||||||
<link rel="stylesheet" href="[[[.CdnPrefix]]]/css/unsubscribe.css">
|
<link rel="stylesheet" href="[[[.CdnPrefix]]]/css/unsubscribe.css">
|
||||||
<title>Commento: Unsubscribe</title>
|
<title>Commento: Email Notification Settings</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<div class="navbar">
|
<div class="navbar">
|
||||||
|
Loading…
Reference in New Issue
Block a user