summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ccxvii.net>2021-11-09 22:33:53 +0100
committerTor Andersson <tor@ccxvii.net>2021-11-09 22:59:49 +0100
commit70289448796f6649d74a2ec22b300c3b0075b762 (patch)
tree87959c4ef3469070bdb36db2ea1de723553a83ef
parent86ee8f02d4230199378eb055a5a89c15844208c9 (diff)
downloadserver-70289448796f6649d74a2ec22b300c3b0075b762.tar.gz
Show user profiles.
-rw-r--r--server.js52
-rw-r--r--tools/sql/schema.txt1
-rw-r--r--views/forum_thread.ejs3
-rw-r--r--views/forum_view.ejs9
-rw-r--r--views/games.ejs4
-rw-r--r--views/info.ejs9
-rw-r--r--views/message_inbox.ejs10
-rw-r--r--views/message_outbox.ejs15
-rw-r--r--views/profile.ejs15
-rw-r--r--views/users.ejs2
10 files changed, 92 insertions, 28 deletions
diff --git a/server.js b/server.js
index f8ab0c3..56f6de5 100644
--- a/server.js
+++ b/server.js
@@ -129,6 +129,18 @@ function humanize(rows) {
}
}
+function linkify_player_names(games) {
+ for (let i = 0; i < games.length; ++i) {
+ let game = games[i];
+ if (game.player_names) {
+ game.player_names = game.player_names
+ .split(", ")
+ .map(x => `<a href="/user/${x}">${x}</a>`)
+ .join(", ");
+ }
+ }
+}
+
function humanize_one(row) {
row.ctime = human_date(row.ctime);
row.mtime = human_date(row.mtime);
@@ -192,6 +204,8 @@ const sql_subscribe = db.prepare("UPDATE users SET notifications = 1 WHERE user_
const sql_unsubscribe = db.prepare("UPDATE users SET notifications = 0 WHERE user_id = ?");
const sql_count_unread_messages = db.prepare("SELECT COUNT(*) FROM messages WHERE to_id = ? AND read = 0 AND deleted_from_inbox = 0").pluck();
+const sql_fetch_user_by_name = db.prepare("SELECT * FROM users WHERE user_id = ? OR name = ?");
+const sql_fetch_user_by_id = db.prepare("SELECT * FROM users WHERE user_id = ?");
passport.serializeUser(function (user, done) {
return done(null, user.user_id);
@@ -346,6 +360,12 @@ app.get('/change_mail', must_be_logged_in, function (req, res) {
res.render('change_mail.ejs', { user: req.user, message: req.flash('message') });
});
+app.get('/change_about', must_be_logged_in, function (req, res) {
+ LOG(req, "GET /change_about");
+ let about = sql_fetch_user_by_id.get(req.user.user_id).about;
+ res.render('change_about.ejs', { user: req.user, about: about || "", message: req.flash('message') });
+});
+
app.get('/subscribe', must_be_logged_in, function (req, res) {
LOG(req, "GET /subscribe");
sql_subscribe.run(req.user.user_id);
@@ -498,6 +518,7 @@ const sql_change_name = db.prepare("UPDATE users SET name = ? WHERE user_id = ?"
const sql_is_mail_taken = db.prepare("SELECT EXISTS ( SELECT 1 FROM users WHERE mail = ? )").pluck();
const sql_change_mail = db.prepare("UPDATE users SET mail = ? WHERE user_id = ?");
+const sql_change_about = db.prepare("UPDATE users SET about = ? WHERE user_id = ?");
app.post('/change_name', must_be_logged_in, function (req, res) {
try {
@@ -543,6 +564,18 @@ app.post('/change_mail', must_be_logged_in, function (req, res) {
}
});
+app.post('/change_about', must_be_logged_in, function (req, res) {
+ try {
+ LOG(req, "POST /change_about", req.user.name);
+ sql_change_about.run(req.body.about, req.user.user_id);
+ return res.redirect('/profile');
+ } catch (err) {
+ console.log(err);
+ req.flash('message', err.message);
+ return res.redirect('/change_about');
+ }
+});
+
/*
* GAME LOBBY
*/
@@ -661,6 +694,7 @@ app.get('/profile', must_be_logged_in, function (req, res) {
let avatar = get_avatar(req.user.mail);
let games = QUERY_LIST_GAMES_OF_USER.all({user_id: req.user.user_id});
humanize(games);
+ linkify_player_names(games);
let open_games = games.filter(game => game.status === 0);
let active_games = games.filter(game => game.status === 1);
let finished_games = games.filter(game => game.status === 2);
@@ -682,6 +716,7 @@ app.get('/info/:title_id', function (req, res) {
if (req.isAuthenticated()) {
let games = QUERY_LIST_GAMES_OF_TITLE.all({user_id: req.user.user_id, title_id: title_id});
humanize(games);
+ linkify_player_names(games);
let open_games = games.filter(game => game.status === 0);
let active_games = games.filter(game => game.status === 1);
let finished_games = games.filter(game => game.status === 2);
@@ -1486,6 +1521,15 @@ app.get('/games', must_be_logged_in, function (req, res) {
});
});
+app.get('/user/:who_id', function (req, res) {
+ LOG(req, "GET /user/" + req.params.who_id);
+ let who = sql_fetch_user_by_name.get(req.params.who_id, req.params.who_id);
+ who.avatar = get_avatar(who.mail);
+ who.ctime = human_date(who.ctime);
+ who.atime = human_date(who.atime);
+ res.render('user.ejs', { user: req.user, who: who, message: req.flash('message') });
+});
+
// FORUM
const FORUM_PAGE_SIZE = 15;
@@ -1621,6 +1665,7 @@ app.post('/forum/reply/:thread_id', must_be_logged_in, function (req, res) {
});
// MESSAGES
+
const MESSAGE_GET_USER = db.prepare("SELECT user_id, name, mail, notifications FROM users WHERE name = ?");
const MESSAGE_GET_USER_ID = db.prepare("SELECT user_id FROM users WHERE name = ?").pluck();
const MESSAGE_GET_USER_NAME = db.prepare("SELECT name FROM users WHERE user_id = ?").pluck();
@@ -1642,6 +1687,7 @@ const MESSAGE_SEND = db.prepare("INSERT INTO messages ( from_id, to_id, subject,
const MESSAGE_MARK_READ = db.prepare("UPDATE messages SET read = 1 WHERE message_id = ?");
const MESSAGE_DELETE_INBOX = db.prepare("UPDATE messages SET deleted_from_inbox = 1 WHERE message_id = ? AND to_id = ?");
const MESSAGE_DELETE_OUTBOX = db.prepare("UPDATE messages SET deleted_from_outbox = 1 WHERE message_id = ? AND from_id = ?");
+const MESSAGE_DELETE_ALL_OUTBOX = db.prepare("UPDATE messages SET deleted_from_outbox = 1 WHERE from_id = ?");
app.get('/inbox', must_be_logged_in, function (req, res) {
LOG(req, "GET /inbox");
@@ -1770,3 +1816,9 @@ app.get('/message/delete/:message_id', must_be_logged_in, function (req, res) {
MESSAGE_DELETE_OUTBOX.run(message_id, req.user.user_id);
res.redirect('/inbox');
});
+
+app.get('/outbox/delete', must_be_logged_in, function (req, res) {
+ LOG(req, "POST /outbox/delete");
+ MESSAGE_DELETE_ALL_OUTBOX.run(req.user.user_id);
+ res.redirect('/outbox');
+});
diff --git a/tools/sql/schema.txt b/tools/sql/schema.txt
index cd1a7ee..6344470 100644
--- a/tools/sql/schema.txt
+++ b/tools/sql/schema.txt
@@ -2,6 +2,7 @@ CREATE TABLE IF NOT EXISTS users (
user_id INTEGER PRIMARY KEY,
name TEXT UNIQUE COLLATE NOCASE,
mail TEXT UNIQUE COLLATE NOCASE,
+ about TEXT,
password TEXT,
salt TEXT,
ctime TIMESTAMP,
diff --git a/views/forum_thread.ejs b/views/forum_thread.ejs
index fad8829..0041f20 100644
--- a/views/forum_thread.ejs
+++ b/views/forum_thread.ejs
@@ -2,6 +2,7 @@
<style>
table { width: 100%; max-width: 50em; }
td.body { white-space: pre-wrap; padding: 10px 10px; }
+th a { color: black; text-decoration: none; }
th.author { border-right: none; }
th.time { text-align: right; border-left: none; font-weight: normal; }
td.edit { text-align: right; border: none; }
@@ -10,7 +11,7 @@ td.edit { text-align: right; border: none; }
<p>
<table>
<tr>
-<th class="nowrap author"><%= row.author_name %>
+<th class="nowrap author"><a href="/user/<%- row.author_name %>"><%= row.author_name %></a>
<th class="nowrap time"><%= row.ctime %>
<%= row.edited ? "(edited " + row.mtime + ")" : "" %>
<tr>
diff --git a/views/forum_view.ejs b/views/forum_view.ejs
index 7c3de75..5f04f3f 100644
--- a/views/forum_view.ejs
+++ b/views/forum_view.ejs
@@ -3,16 +3,19 @@
table { width: 100%; max-width: 60em; }
td a { color: black; text-decoration: none; }
tfoot td { background-color: gainsboro; }
+th.replies { width: 3em; }
+th.time { width: 5em; }
+th.author { width: 10em; }
</style>
<table>
<thead>
-<tr><th>Subject<th>Author
-<th>Replies<th>Time
+<tr><th class="subject">Subject<th class="author">Author
+<th class="replies">Replies<th class="time">Time
</thead>
<% threads.forEach((row) => { %>
<tr>
<td class="ellipsis"><a href="/forum/thread/<%- row.thread_id %>"><%= row.subject %></a>
-<td class="nowrap"><%= row.author_name %>
+<td class="nowrap"><a href="/user/<%- row.author_name %>"><%= row.author_name %></a>
<td><%= row.reply_count %>
<td class="nowrap"><%= row.mtime %>
<% }); %>
diff --git a/views/games.ejs b/views/games.ejs
index e25df1f..b74dbba 100644
--- a/views/games.ejs
+++ b/views/games.ejs
@@ -12,7 +12,7 @@ td.nowrap a { color: black; text-decoration: none; }
<td><%= row.game_id %>
<td class="nowrap"><a href="/info/<%= row.title_id %>"><%= row.title_name %></a>
<td><%= row.scenario %>
-<td><%= row.player_names || row.owner_name %>
+<td><%- row.player_names || row.owner_name %>
<td><%= row.description %>
<td class="nowrap"><%= row.ctime %>
<td><a href="/join/<%= row.game_id %>">Join</a>
@@ -30,7 +30,7 @@ td.nowrap a { color: black; text-decoration: none; }
<td><%= row.game_id %>
<td class="nowrap"><a href="/info/<%= row.title_id %>"><%= row.title_name %></a>
<td><%= row.scenario %>
-<td><%= row.player_names %>
+<td><%- row.player_names %>
<td><%= row.description %>
<td class="nowrap"><%= row.mtime %>
<td class="<%= row.is_your_turn ? "is_your_turn" : "" %>"><%= row.active_role %>
diff --git a/views/info.ejs b/views/info.ejs
index 778974e..159e732 100644
--- a/views/info.ejs
+++ b/views/info.ejs
@@ -1,4 +1,7 @@
<%- include('header', { title: title.title_name, refresh: (user ? 300 : 0) }) %>
+<style>
+td.names a { color: black; text-decoration: none; }
+</style>
<img class="logo" src="/<%= title.title_id %>/cover.jpg">
<%- include('../public/' + title.title_id + '/about.html') %>
<p>
@@ -15,7 +18,7 @@ Read more about the game on
<tr>
<td><%= row.game_id %>
<td><%= row.scenario %>
-<td><%= row.player_names || row.owner_name %>
+<td class="names"><%- row.player_names || `<a href="/user/${row.owner_name}">${row.owner_name}</a>` %>
<td><%= row.description %>
<td class="nowrap"><%= row.ctime %>
<td><a href="/join/<%= row.game_id %>">Join</a>
@@ -35,7 +38,7 @@ Read more about the game on
<tr>
<td><%= row.game_id %>
<td><%= row.scenario %>
-<td><%= row.player_names %>
+<td class="names"><%- row.player_names %>
<td><%= row.description %>
<td class="nowrap"><%= row.mtime %>
<td class="<%= row.is_your_turn ? "is_your_turn" : "" %>"><%= row.active_role %>
@@ -52,7 +55,7 @@ Read more about the game on
<tr>
<td><%= row.game_id %>
<td><%= row.scenario %>
-<td><%= row.player_names %>
+<td class="names"><%- row.player_names %>
<td><%= row.description %>
<td class="nowrap"><%= row.mtime %>
<td><%= row.result %>
diff --git a/views/message_inbox.ejs b/views/message_inbox.ejs
index 91490ac..16b0c46 100644
--- a/views/message_inbox.ejs
+++ b/views/message_inbox.ejs
@@ -1,23 +1,21 @@
<%- include('header', { title: "Inbox" }) %>
<style>
table { width: 100%; max-width: 50em; }
-tr.unread { background-color: lemonchiffon; }
+tr.unread { background-color: lightyellow; }
td.from { width: 5em; }
td.time { text-align: right; width: 5em; }
td a { color:black; text-decoration: none; }
</style>
-<p>
-&#xbb; <a href="/message/send">Send message</a>
-<br>
-&#xbb; <a href="/outbox">Outbox</a>
+<p><a href="/message/send">Send message</a>
<table>
<tr><th>From<th>Subject<th>Date
<% if (messages.length > 0) { messages.forEach((row) => { %>
<tr class="<%- row.read ? "read" : "unread" %>">
-<td class="nowrap from"><%= row.from_name %>
+<td class="nowrap from"><a href="/user/<%- row.from_name %>"><%= row.from_name %></a>
<td class="subject"><a href="/message/read/<%- row.message_id %>"><%= row.subject %></a>
<td class="nowrap time"><%= row.time %>
<% }); } else { %>
<tr><td colspan="3">No messages</td>
<% } %>
</table>
+<p><a href="/outbox">Outbox</a>
diff --git a/views/message_outbox.ejs b/views/message_outbox.ejs
index c460bd3..e5c53e3 100644
--- a/views/message_outbox.ejs
+++ b/views/message_outbox.ejs
@@ -1,4 +1,11 @@
<%- include('header', { title: "Outbox" }) %>
+<script>
+function delete_all() {
+ let warning = "Are you sure you want to delete ALL the messages?";
+ if (window.confirm(warning))
+ window.location.href = "/outbox/delete";
+}
+</script>
<style>
table { width: 100%; max-width: 50em; }
tr.unread { background-color: lemonchiffon; }
@@ -6,18 +13,16 @@ td.to { width: 5em; }
td.time { text-align: right; width: 5em; }
td a { color:black; text-decoration: none; }
</style>
-<p>
-&#xbb; <a href="/message/send">Send message</a>
-<br>
-&#xbb; <a href="/inbox">Inbox</a>
<table>
<tr><th>To<th>Subject<th>Date
<% if (messages.length > 0) { messages.forEach((row) => { %>
<tr class="<%- row.read ? "read" : "unread" %>">
-<td class="nowrap to"><%= row.to_name %>
+<td class="nowrap to"><a href="/user/<%- row.to_name %>"><%= row.to_name %></a>
<td class="subject"><a href="/message/read/<%- row.message_id %>"><%= row.subject %></a>
<td class="nowrap time"><%= row.time %>
<% }); } else { %>
<tr><td colspan="3">No messages</td>
<% } %>
</table>
+<p>
+<button onclick="delete_all()">Delete all</button>
diff --git a/views/profile.ejs b/views/profile.ejs
index 8d03234..3c49014 100644
--- a/views/profile.ejs
+++ b/views/profile.ejs
@@ -1,6 +1,6 @@
<%- include('header', { title: "Rally the Troops!", refresh: (active_games.length > 0 ? 300 : 0) }) %>
<style>
-td.nowrap a { color: black; text-decoration: none; }
+td.game a, td.names a { color: black; text-decoration: none; }
.logo { width: 80px; height: 80px; }
</style>
@@ -23,6 +23,7 @@ Your mail address is <%= user.mail %>.
<li><a href="/change_password">Change password</a>
<li><a href="/change_mail">Change mail address</a>
<li><a href="/change_name">Change name</a>
+<li><a href="/change_about">Change profile text</a>
<li><a href="/logout">Logout</a>
</ul>
@@ -33,9 +34,9 @@ Your mail address is <%= user.mail %>.
<% open_games.forEach((row) => { %>
<tr>
<td><%= row.game_id %>
-<td class="nowrap"><a href="/info/<%= row.title_id %>"><%= row.title_name %></a>
+<td class="nowrap game"><a href="/info/<%= row.title_id %>"><%= row.title_name %></a>
<td><%= row.scenario %>
-<td><%= row.player_names %>
+<td class="names"><%- row.player_names %>
<td><%= row.description %>
<td class="nowrap"><%= row.ctime %>
<td><a href="/join/<%= row.game_id %>">Join</a>
@@ -50,9 +51,9 @@ Your mail address is <%= user.mail %>.
<% active_games.forEach((row) => { %>
<tr>
<td><%= row.game_id %>
-<td class="nowrap"><a href="/info/<%= row.title_id %>"><%= row.title_name %></a>
+<td class="nowrap game"><a href="/info/<%= row.title_id %>"><%= row.title_name %></a>
<td><%= row.scenario %>
-<td><%= row.player_names %>
+<td class="names"><%- row.player_names %>
<td><%= row.description %>
<td class="nowrap"><%= row.mtime %>
<%
@@ -78,9 +79,9 @@ Your mail address is <%= user.mail %>.
<% finished_games.forEach((row) => { %>
<tr>
<td><%= row.game_id %>
-<td class="nowrap"><a href="/info/<%= row.title_id %>"><%= row.title_name %></a>
+<td class="nowrap game"><a href="/info/<%= row.title_id %>"><%= row.title_name %></a>
<td><%= row.scenario %>
-<td><%= row.player_names %>
+<td class="names"><%- row.player_names %>
<td><%= row.description %>
<td class="nowrap"><%= row.mtime %>
<td><%= row.result %>
diff --git a/views/users.ejs b/views/users.ejs
index 526b722..d6e4d4a 100644
--- a/views/users.ejs
+++ b/views/users.ejs
@@ -10,7 +10,7 @@ td.avatar img{display:block;width:80px;height:80px;}
<% userList.forEach((row) => { %>
<tr>
<td class="avatar"><img src="<%= row.avatar %>">
-<td><a href="/user/<%= row.user_id %>"><%= row.name %></a>
+<td><a href="/user/<%= row.name %>"><%= row.name %></a>
<td><%= row.ctime %>
<td><%= row.atime %>
<% }); %>