From 9f67e66b83d158b99582c2984fc253b6e6abd537 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Thu, 1 May 2025 22:04:10 +0200 Subject: Simplify form post actions. Put account management pages under "/account" URL prefix. Set logged in user in res.locals for use in pug templates. Tweak verification flow. Require password to change name and mail. Show user statistics on profile (use pug mixin). Remove "api" prefix on many routes. --- views/account_change_about.pug | 27 +++++++++++++ views/account_change_mail.pug | 26 ++++++++++++ views/account_change_name.pug | 26 ++++++++++++ views/account_change_password.pug | 26 ++++++++++++ views/account_delete.pug | 28 +++++++++++++ views/account_forgot_password.pug | 25 ++++++++++++ views/account_mail_verify.pug | 32 +++++++++++++++ views/account_reset_password.pug | 31 +++++++++++++++ views/account_webhook.pug | 68 ++++++++++++++++++++++++++++++++ views/change_about.pug | 27 ------------- views/change_mail.pug | 22 ----------- views/change_name.pug | 22 ----------- views/change_password.pug | 26 ------------ views/contacts_search.pug | 31 +++++++++++++++ views/create-index.pug | 16 -------- views/create.pug | 83 --------------------------------------- views/create_index.pug | 16 ++++++++ views/create_title.pug | 83 +++++++++++++++++++++++++++++++++++++++ views/delete_account.pug | 28 ------------- views/forgot_password.pug | 25 ------------ views/game_stats.pug | 25 ------------ views/head.pug | 33 ++++++++++++++++ views/info.pug | 41 ------------------- views/login.pug | 4 +- views/profile.pug | 65 +++++++++++++++++++----------- views/reset_password.pug | 31 --------------- views/search_user.pug | 31 --------------- views/signup.pug | 2 +- views/stats_title.pug | 25 ++++++++++++ views/stats_user.pug | 53 +++++++++++++++++++++++++ views/title.pug | 41 +++++++++++++++++++ views/tm_seed.pug | 6 +-- views/user.pug | 34 +--------------- views/user_stats.pug | 53 ------------------------- views/verify_mail.pug | 21 ---------- views/webhook.pug | 68 -------------------------------- 36 files changed, 620 insertions(+), 581 deletions(-) create mode 100644 views/account_change_about.pug create mode 100644 views/account_change_mail.pug create mode 100644 views/account_change_name.pug create mode 100644 views/account_change_password.pug create mode 100644 views/account_delete.pug create mode 100644 views/account_forgot_password.pug create mode 100644 views/account_mail_verify.pug create mode 100644 views/account_reset_password.pug create mode 100644 views/account_webhook.pug delete mode 100644 views/change_about.pug delete mode 100644 views/change_mail.pug delete mode 100644 views/change_name.pug delete mode 100644 views/change_password.pug create mode 100644 views/contacts_search.pug delete mode 100644 views/create-index.pug delete mode 100644 views/create.pug create mode 100644 views/create_index.pug create mode 100644 views/create_title.pug delete mode 100644 views/delete_account.pug delete mode 100644 views/forgot_password.pug delete mode 100644 views/game_stats.pug delete mode 100644 views/info.pug delete mode 100644 views/reset_password.pug delete mode 100644 views/search_user.pug create mode 100644 views/stats_title.pug create mode 100644 views/stats_user.pug create mode 100644 views/title.pug delete mode 100644 views/user_stats.pug delete mode 100644 views/verify_mail.pug delete mode 100644 views/webhook.pug (limited to 'views') diff --git a/views/account_change_about.pug b/views/account_change_about.pug new file mode 100644 index 0000000..7a0531e --- /dev/null +++ b/views/account_change_about.pug @@ -0,0 +1,27 @@ +//- vim:ts=4:sw=4: +doctype html +html + head + include head + title Change profile text + style. + input, textarea { width: min(45rem,100%) } + body + include header + article + h1 Change profile text + form(method="post") + p Name: #{user.name} + p Mail: #{user.mail} + p + textarea( + name="about" + rows=20 + cols=80 + maxlength=32000 + autofocus + ) + | + | #{about} + p + button(type="submit") Submit diff --git a/views/account_change_mail.pug b/views/account_change_mail.pug new file mode 100644 index 0000000..4d0605a --- /dev/null +++ b/views/account_change_mail.pug @@ -0,0 +1,26 @@ +//- vim:ts=4:sw=4: +doctype html +html + head + include head + title Change mail address + body + include header + article + h1 Change mail address + if flash + p.error= flash + + form(method="post") + p Name: #{user.name} + p Mail: #{user.mail} + p + label New mail address: + br + input(type="text" name="newmail" required) + p + label Password: + br + input(type="password" name="password" required) + p + button(type="submit") Change mail diff --git a/views/account_change_name.pug b/views/account_change_name.pug new file mode 100644 index 0000000..b1845ab --- /dev/null +++ b/views/account_change_name.pug @@ -0,0 +1,26 @@ +//- vim:ts=4:sw=4: +doctype html +html + head + include head + title Change name + body + include header + article + h1 Change name + if flash + p.error= flash + + form(method="post") + p Name: #{user.name} + p Mail: #{user.mail} + p + label New name: + br + input(type="text" name="newname" required) + p + label Password: + br + input(type="password" name="password" required) + p + button(type="submit") Change name diff --git a/views/account_change_password.pug b/views/account_change_password.pug new file mode 100644 index 0000000..ca8e973 --- /dev/null +++ b/views/account_change_password.pug @@ -0,0 +1,26 @@ +//- vim:ts=4:sw=4: +doctype html +html + head + include head + title Change password + body + include header + article + h1 Change password + if flash + p.error= flash + + form(method="post") + p Name: #{user.name} + p Mail: #{user.mail} + p + label Old Password: + br + input(type="password" name="password" required) + p + label New Password: + br + input(type="password" name="newpass" required) + p + button(type="submit") Change password diff --git a/views/account_delete.pug b/views/account_delete.pug new file mode 100644 index 0000000..54c3bc4 --- /dev/null +++ b/views/account_delete.pug @@ -0,0 +1,28 @@ +//- vim:ts=4:sw=4: +doctype html +html + head + include head + title Delete account + body + include header + article + h1 Delete account + if flash + p.error= flash + + form(method="post") + p Name: #{user.name} + p Mail: #{user.mail} + p + label Password: + br + input(type="password" name="password" required) + p + label Type DELETE to confirm: + br + input(type="text" name="confirm" pattern="^DELETE$" required) + p.warning WARNING: Deleting your account is permanent! + p All your games and messages will be lost forever. + p + button(type="submit") Delete! diff --git a/views/account_forgot_password.pug b/views/account_forgot_password.pug new file mode 100644 index 0000000..0913857 --- /dev/null +++ b/views/account_forgot_password.pug @@ -0,0 +1,25 @@ +//- vim:ts=4:sw=4: +doctype html +html + head + include head + title Forgot password + +altcha_script() + body + include header + article + h1 Forgot password + if flash + p.error= flash + + if user + p You're already logged in! + else + form(method="post") + p + label Mail: + br + input(type="email" name="mail" required) + +altcha_widget() + p + button(type="submit") Forgot password diff --git a/views/account_mail_verify.pug b/views/account_mail_verify.pug new file mode 100644 index 0000000..fddf2fa --- /dev/null +++ b/views/account_mail_verify.pug @@ -0,0 +1,32 @@ +//- vim:ts=4:sw=4: +doctype html +html + head + include head + title Verify mail + body + include header + article + h1 Verify mail + if flash + p.error= flash + + p Your mail address is #{user.mail} + + p If the above address is wrong, you can change it! + + if sent_token + p Your token is in the mail! + else + form(method="post" action="/account/mail/verify-send") + p + button(type="submit") Send token + + form(method="post") + p + label Enter your mail verification token here: + br + input(type="text" name="token" size=32 value=token style="font-family:monospace" required) + p + button(type="submit") Verify + diff --git a/views/account_reset_password.pug b/views/account_reset_password.pug new file mode 100644 index 0000000..8707ebc --- /dev/null +++ b/views/account_reset_password.pug @@ -0,0 +1,31 @@ +//- vim:ts=4:sw=4: +doctype html +html + head + include head + title Reset password + body + include header + article + h1 Reset password + if flash + p.error= flash + + p You should have received a password reset token in your mail. + + form(method="post") + p + label Mail: + br + input(type="email" name="mail" size=32 value=mail required) + p + label New Password: + br + input(type="password" name="password" size=32 required) + p + label Token: + br + input(type="text" name="token" size=32 value=token style="font-family:monospace" required) + +altcha_widget() + p + button(type="submit") Reset password diff --git a/views/account_webhook.pug b/views/account_webhook.pug new file mode 100644 index 0000000..b9817ef --- /dev/null +++ b/views/account_webhook.pug @@ -0,0 +1,68 @@ +//- vim:ts=4:sw=4: +doctype html +html(lang="en") + head + include head + title Webhook + body + include header + article + + h1 Webhook + + - var url = webhook && webhook.url || "" + - var format = webhook && webhook.format || "" + - var prefix = webhook && webhook.prefix || "" + + form(action="/account/webhook/update" method="post") + if webhook && webhook.error + p.error ERROR: #{webhook.error} + p Webhook URL: + br + input#url(type="text" name="url" size=120 placeholder="https://discord.com/api/webhooks/..." value=url required) + p Webhook format: + br + input#format(type="text" name="format" size=40 placeholder="content" value=format) + + p Message prefix: + br + input#prefix(type="text" name="prefix" size=40 placeholder="<@123456789>" value=prefix) + + if webhook + button(type="submit") Update + else + button(type="submit") Create + + if webhook + form(action="/account/webhook/delete" method="post") + button(type="submit") Delete + + h2 Discord Notifications + + p You can send notifications to a given channel on a Discord server. + + ol + li Create your own server or use an existing server where you have administrator privileges. + li Get the webhook URL for the Discord channel and enter it into the Webhook URL field. + li Enter "content" into the Webhook format field. + li Find your Discord User ID. This is not your username, it is a number. + li Enter your Discord User ID into the Message prefix field as "<@12345>". + + h2 Slack Notifications + + p You can send notifications to a Slack workspace. + + ol + li Join or set up a Slack workspace with a webhook integration. + li Find the Webhook URL and enter it into the Webhook URL field. + li Enter "text" into the Webhook format field. + li Find your Slack User ID. This is a number with "U" in front of it. + li Enter your Slack User ID into the Message prefix field as "<@U12345>". + + h2 Custom Notifications + + p. + You can integrate with any server that accepts inbound webhooks by setting the webhook URL to the appropriate endpoint. + If the format field is blank, the payload is sent as plain text. + Otherwise, the payload is a JSON object where the format field specifies which JSON property holds the message. + Use "content" for Discord and "text" for Slack. diff --git a/views/change_about.pug b/views/change_about.pug deleted file mode 100644 index b5e2c84..0000000 --- a/views/change_about.pug +++ /dev/null @@ -1,27 +0,0 @@ -//- vim:ts=4:sw=4: -doctype html -html - head - include head - title Change profile text - style. - input, textarea { width: min(45rem,100%) } - body - include header - article - h1 Change profile text - form(method="post" action="/change-about") - p Name: #{user.name} - p Mail: #{user.mail} - p - textarea( - name="about" - rows=20 - cols=80 - maxlength=32000 - autofocus - ) - | - | #{about} - p - button(type="submit") Submit diff --git a/views/change_mail.pug b/views/change_mail.pug deleted file mode 100644 index d244e98..0000000 --- a/views/change_mail.pug +++ /dev/null @@ -1,22 +0,0 @@ -//- vim:ts=4:sw=4: -doctype html -html - head - include head - title Change mail address - body - include header - article - h1 Change mail address - if flash - p.error= flash - - form(method="post" action="/change-mail") - p Name: #{user.name} - p Mail: #{user.mail} - p - label New mail address: - br - input(type="text" name="newmail" required) - p - button(type="submit") Change mail diff --git a/views/change_name.pug b/views/change_name.pug deleted file mode 100644 index 03763ac..0000000 --- a/views/change_name.pug +++ /dev/null @@ -1,22 +0,0 @@ -//- vim:ts=4:sw=4: -doctype html -html - head - include head - title Change name - body - include header - article - h1 Change name - if flash - p.error= flash - - form(method="post" action="/change-name") - p Name: #{user.name} - p Mail: #{user.mail} - p - label New name: - br - input(type="text" name="newname" required) - p - button(type="submit") Change name diff --git a/views/change_password.pug b/views/change_password.pug deleted file mode 100644 index 022a67c..0000000 --- a/views/change_password.pug +++ /dev/null @@ -1,26 +0,0 @@ -//- vim:ts=4:sw=4: -doctype html -html - head - include head - title Change password - body - include header - article - h1 Change password - if flash - p.error= flash - - form(method="post" action="/change-password") - p Name: #{user.name} - p Mail: #{user.mail} - p - label Old Password: - br - input(type="password" name="password" required) - p - label New Password: - br - input(type="password" name="newpass" required) - p - button(type="submit") Change password diff --git a/views/contacts_search.pug b/views/contacts_search.pug new file mode 100644 index 0000000..308cc41 --- /dev/null +++ b/views/contacts_search.pug @@ -0,0 +1,31 @@ +//- vim:ts=4:sw=4: +doctype html +html + head + include head + title User Search Results + body + include header + article + + h1 User Search Results + + if results && search + if results.length > 0 + table.half.striped + thead + tr + th Name + th Last seen + tbody + each who in results + tr + td + a.black(href="/user/"+who.name)= who.name + td.w= human_date(who.atime) + else + p.error Nobody found matching "#{search}". + + p + form(method="get" action="/contacts/search") + input(type="text" name="q" size=40 placeholder="Find user..." value=search required) diff --git a/views/create-index.pug b/views/create-index.pug deleted file mode 100644 index c508be7..0000000 --- a/views/create-index.pug +++ /dev/null @@ -1,16 +0,0 @@ -//- vim:ts=4:sw=4: -doctype html -html - head - include head - title Create game - body - include header - article - h1 Create a new game - - ul - each title in TITLE_LIST - unless title.is_hidden - li - a(href="/create/"+title.title_id)= title.title_name diff --git a/views/create.pug b/views/create.pug deleted file mode 100644 index c4c5c2a..0000000 --- a/views/create.pug +++ /dev/null @@ -1,83 +0,0 @@ -//- vim:ts=4:sw=4: -doctype html -html - head - include head - title= title.title_name - body - include header - article - - h1= title.title_name - - div.logo - +gamecover(title.title_id) - - if limit - p.error= limit - if !user - p.error You are not logged in! - - form(method="post" action="/create/"+title.title_id) - if Array.isArray(rules.scenarios) - if rules.scenarios.length > 1 - p Scenario: - br - select(name="scenario") - each scenario in rules.scenarios - if scenario === rules.default_scenario - option(value=scenario selected)= scenario - else - option(value=scenario)= scenario - else - input(type="hidden" name="scenario" value=rules.scenarios[0]) - else - p Scenario: - br - select(name="scenario") - each list, name in rules.scenarios - if name === "" - each scenario in list - if scenario === rules.default_scenario - option(value=scenario selected)= scenario - else - option(value=scenario)= scenario - else - optgroup(label=name) - each scenario in list - if scenario === rules.default_scenario - option(value=scenario selected)= scenario - else - option(value=scenario)= scenario - - | !{ title.create_html } - - if user - p Notice: - br - input(type="text" autocomplete="off" name="notice" size=45 placeholder="What are you looking for?") - - p Pace: - each text, pace in PACE_TEXT - br - label - input(type="radio" name="pace" value=pace checked=pace===0) - | #{PACE_ICON[pace]} #{text} - - p - label - input(type="checkbox" name="is_random" value="true") - | Random player roles - - p - label - input(type="checkbox" name="is_private" value="true") - | Private - - if !limit - p - button(type="submit") Create - - else - p Login or sign up to play. - diff --git a/views/create_index.pug b/views/create_index.pug new file mode 100644 index 0000000..c508be7 --- /dev/null +++ b/views/create_index.pug @@ -0,0 +1,16 @@ +//- vim:ts=4:sw=4: +doctype html +html + head + include head + title Create game + body + include header + article + h1 Create a new game + + ul + each title in TITLE_LIST + unless title.is_hidden + li + a(href="/create/"+title.title_id)= title.title_name diff --git a/views/create_title.pug b/views/create_title.pug new file mode 100644 index 0000000..c4c5c2a --- /dev/null +++ b/views/create_title.pug @@ -0,0 +1,83 @@ +//- vim:ts=4:sw=4: +doctype html +html + head + include head + title= title.title_name + body + include header + article + + h1= title.title_name + + div.logo + +gamecover(title.title_id) + + if limit + p.error= limit + if !user + p.error You are not logged in! + + form(method="post" action="/create/"+title.title_id) + if Array.isArray(rules.scenarios) + if rules.scenarios.length > 1 + p Scenario: + br + select(name="scenario") + each scenario in rules.scenarios + if scenario === rules.default_scenario + option(value=scenario selected)= scenario + else + option(value=scenario)= scenario + else + input(type="hidden" name="scenario" value=rules.scenarios[0]) + else + p Scenario: + br + select(name="scenario") + each list, name in rules.scenarios + if name === "" + each scenario in list + if scenario === rules.default_scenario + option(value=scenario selected)= scenario + else + option(value=scenario)= scenario + else + optgroup(label=name) + each scenario in list + if scenario === rules.default_scenario + option(value=scenario selected)= scenario + else + option(value=scenario)= scenario + + | !{ title.create_html } + + if user + p Notice: + br + input(type="text" autocomplete="off" name="notice" size=45 placeholder="What are you looking for?") + + p Pace: + each text, pace in PACE_TEXT + br + label + input(type="radio" name="pace" value=pace checked=pace===0) + | #{PACE_ICON[pace]} #{text} + + p + label + input(type="checkbox" name="is_random" value="true") + | Random player roles + + p + label + input(type="checkbox" name="is_private" value="true") + | Private + + if !limit + p + button(type="submit") Create + + else + p Login or sign up to play. + diff --git a/views/delete_account.pug b/views/delete_account.pug deleted file mode 100644 index e16e1b6..0000000 --- a/views/delete_account.pug +++ /dev/null @@ -1,28 +0,0 @@ -//- vim:ts=4:sw=4: -doctype html -html - head - include head - title Delete account - body - include header - article - h1 Delete account - if flash - p.error= flash - - form(method="post" action="/delete-account") - p Name: #{user.name} - p Mail: #{user.mail} - p - label Password: - br - input(type="password" name="password" required) - p - label Type DELETE to confirm: - br - input(type="text" name="confirm" pattern="^DELETE$" required) - p.warning WARNING: Deleting your account is permanent! - p All your games and messages will be lost forever. - p - button(type="submit") Delete! diff --git a/views/forgot_password.pug b/views/forgot_password.pug deleted file mode 100644 index 935cae1..0000000 --- a/views/forgot_password.pug +++ /dev/null @@ -1,25 +0,0 @@ -//- vim:ts=4:sw=4: -doctype html -html - head - include head - title Forgot password - +altcha_script() - body - include header - article - h1 Forgot password - if flash - p.error= flash - - if user - p You're already logged in! - else - form(method="post" action="/forgot-password") - p - label Mail: - br - input(type="email" name="mail" required) - +altcha_widget() - p - button(type="submit") Forgot password diff --git a/views/game_stats.pug b/views/game_stats.pug deleted file mode 100644 index 692c30b..0000000 --- a/views/game_stats.pug +++ /dev/null @@ -1,25 +0,0 @@ -//- vim:ts=4:sw=4: -doctype html -html - head - include head - title #{title_name} - Ranking - body - include header - article - h1 #{title_name} - Ranking - - table.striped - thead - tr - th Player - th.r Rating - th.r Plays - th.r Last played - tbody - each row in ratings - tr - td= row.name - td.r= row.rating - td.r= row.count - td.r= row.last diff --git a/views/head.pug b/views/head.pug index eec1299..da73d4e 100644 --- a/views/head.pug +++ b/views/head.pug @@ -212,3 +212,36 @@ mixin tourlist(seeds, pools, fin) +poollist(pools, "Active", TM_ICON_ACTIVE) div +poollist(fin, "Finished", TM_ICON_FINISHED) + +mixin userstats(who, ratings) + if (who.move_time_mean !== null) + h3 Response time + div Average response time: #{format_minutes(who.move_time_mean)} + if (who.move_time_q2 !== null) + div Median response time: #{format_minutes(who.move_time_q2)} + if (who.move_time_q1 !== null && who.move_time_q2 !== null) + div Middle half of response times: #{format_minutes(who.move_time_q1)} to #{format_minutes(who.move_time_q3)} + + h3 Timeouts + div Total number of timeouts: #{who.timeout_total} + div Games completed since last timeout: #{who.games_since_timeout} + + if ratings.length > 0 + h3 Most played games + table + thead + tr + th Title + th Count + th Last played + if user && user.user_id === 1 + th Elo + tbody + each row in ratings + tr + td + a.black(href="/" + row.title_id)= row.title_name + td.r= row.count + td.r= row.last + if user && user.user_id === 1 + td.r= row.rating diff --git a/views/info.pug b/views/info.pug deleted file mode 100644 index 32837e9..0000000 --- a/views/info.pug +++ /dev/null @@ -1,41 +0,0 @@ -//- vim:ts=4:sw=4: -doctype html -html - head - include head - +social(title.title_name, "Play " + title.title_name + " on the web.", title.title_id) - title= title.title_name - body - include header - article - h1= title.title_name - - div.logo - +gamecover(title.title_id) - - | !{ title.about_html } - - p Read more about the game on #[a(href="https://boardgamegeek.com/boardgame/"+title.bgg) boardgamegeek.com]. - - h2 Open - if open_games.length > 0 - +gamelist(open_games, true) - else - p No open games right now. - - p - a(href="/create/"+title.title_id) Create a new game - - if replacement_games.length > 0 - h2 Open (missing players) - +gamelist(replacement_games, true) - - +tourlist(seeds, active_pools, finished_pools) - - if active_games.length > 0 - h2 Recently active - +gamelist(active_games, true) - - if finished_games.length > 0 - h2 Recently finished - +gamelist(finished_games, true) diff --git a/views/login.pug b/views/login.pug index 9a44b44..ec8be48 100644 --- a/views/login.pug +++ b/views/login.pug @@ -19,7 +19,7 @@ html p You need to be logged in to view this page! p Log in below, or sign up for a free account. - form(method="post" action="/login") + form(method="post") input(type="hidden" name="redirect" value=redirect) p label Name or mail: @@ -33,4 +33,4 @@ html p button(type="submit") Login p - a(href="/forgot-password") Forgot password + a(href="/account/forgot-password") Forgot password diff --git a/views/profile.pug b/views/profile.pug index 4ecf289..fc9a1d3 100644 --- a/views/profile.pug +++ b/views/profile.pug @@ -7,43 +7,60 @@ html body include header article - h1= SITE_NAME + h1 Profile p Welcome, #{user.name}! + + if who.about + p.box= who.about + + p Member since #{human_date(who.ctime)}. + + +userstats(who, ratings) + + h3 Notifications + p Your mail address is #{user.mail} if ENABLE_MAIL - if !user.is_verified - p ⚠ Verify your mail address! + if !mail.is_verified + p ⚠ Verify your mail address! p You must verify your mail address before you can enable notifications. else - if !user.notify - p Enable mail notifications - if user.notify - p Disable mail notifications + if !mail.notify + p Enable mail notifications + if mail.notify + p Disable mail notifications + else + p.error Mail notifications are disabled on this server. + + if ENABLE_WEBHOOKS + if !webhook + p Configure webhook + else if webhook.error + dl + dt Configure webhook + dd.error ERROR: #{webhook.error} + else + dl + dt Configure webhook + dd= new URL(webhook.url).hostname + else + p.error Webhook notifications are disabled on this server. + + h3 Account p - | Change password + | Change password br - | Change mail address + | Change mail address br - | Change user name + | Change user name br - | Change profile text - br - | Delete account + | Change profile text - if ENABLE_WEBHOOKS - if !user.webhook - p Configure webhook - else if user.webhook.error - dl - dt Configure webhook - dd.error ERROR: #{user.webhook.error} - else - dl - dt Configure webhook - dd= new URL(user.webhook.url).hostname + p + | Delete account p form(action="/logout" method="post") diff --git a/views/reset_password.pug b/views/reset_password.pug deleted file mode 100644 index 2fda418..0000000 --- a/views/reset_password.pug +++ /dev/null @@ -1,31 +0,0 @@ -//- vim:ts=4:sw=4: -doctype html -html - head - include head - title Reset password - body - include header - article - h1 Reset password - if flash - p.error= flash - - p You should have received a password reset token in your mail. - - form(method="post" action="/reset-password") - p - label Mail: - br - input(type="email" name="mail" size=32 value=mail required) - p - label New Password: - br - input(type="password" name="password" size=32 required) - p - label Token: - br - input(type="text" name="token" size=32 value=token style="font-family:monospace" required) - +altcha_widget() - p - button(type="submit") Reset password diff --git a/views/search_user.pug b/views/search_user.pug deleted file mode 100644 index 308cc41..0000000 --- a/views/search_user.pug +++ /dev/null @@ -1,31 +0,0 @@ -//- vim:ts=4:sw=4: -doctype html -html - head - include head - title User Search Results - body - include header - article - - h1 User Search Results - - if results && search - if results.length > 0 - table.half.striped - thead - tr - th Name - th Last seen - tbody - each who in results - tr - td - a.black(href="/user/"+who.name)= who.name - td.w= human_date(who.atime) - else - p.error Nobody found matching "#{search}". - - p - form(method="get" action="/contacts/search") - input(type="text" name="q" size=40 placeholder="Find user..." value=search required) diff --git a/views/signup.pug b/views/signup.pug index 63b9ab3..5dec458 100644 --- a/views/signup.pug +++ b/views/signup.pug @@ -15,7 +15,7 @@ html if user p You're already logged in! else - form(method="post" action="/signup") + form(method="post") p You need to sign up for a free account to play games on #{SITE_NAME_P} p label Name: diff --git a/views/stats_title.pug b/views/stats_title.pug new file mode 100644 index 0000000..aed6e63 --- /dev/null +++ b/views/stats_title.pug @@ -0,0 +1,25 @@ +//- vim:ts=4:sw=4: +doctype html +html + head + include head + title #{title_name} - Ranking + body + include header + article + h1 #{title_name} - Ranking + + table.striped + thead + tr + th Player + th.r Rating + th.r Plays + th.r Last played + tbody + each row in ratings + tr + td #{row.name} + td.r= row.rating + td.r= row.count + td.r= row.last diff --git a/views/stats_user.pug b/views/stats_user.pug new file mode 100644 index 0000000..3b201ef --- /dev/null +++ b/views/stats_user.pug @@ -0,0 +1,53 @@ +//- vim:ts=4:sw=4: +- let all_won = 0 +- let all_total = 0 +doctype html +html + head + include head + title Statistics for #{who.name} + body + include header + article + h1 Statistics for #{who.name} + + table.striped + thead + tr + th Title + th Scenario + th Role + th.r Played + th.r Won + tbody + each row in stats + tr + - all_won += row.won + - all_total += row.total + td= row.title_name + td= row.scenario + td= row.role + td.r= row.total + td.r= Math.round(row.won*100/row.total) + "%" + tfoot + tr + td Overall + td + td + td.r= all_total + td.r= Math.round(all_won*100/all_total) + "%" + + table.striped + thead + tr + th Title + th.r Rating + th.r Plays + th.r Last played + tbody + each row in ratings + tr + td= row.title_name + td.r= row.rating + td.r= row.count + td.r= row.last diff --git a/views/title.pug b/views/title.pug new file mode 100644 index 0000000..32837e9 --- /dev/null +++ b/views/title.pug @@ -0,0 +1,41 @@ +//- vim:ts=4:sw=4: +doctype html +html + head + include head + +social(title.title_name, "Play " + title.title_name + " on the web.", title.title_id) + title= title.title_name + body + include header + article + h1= title.title_name + + div.logo + +gamecover(title.title_id) + + | !{ title.about_html } + + p Read more about the game on #[a(href="https://boardgamegeek.com/boardgame/"+title.bgg) boardgamegeek.com]. + + h2 Open + if open_games.length > 0 + +gamelist(open_games, true) + else + p No open games right now. + + p + a(href="/create/"+title.title_id) Create a new game + + if replacement_games.length > 0 + h2 Open (missing players) + +gamelist(replacement_games, true) + + +tourlist(seeds, active_pools, finished_pools) + + if active_games.length > 0 + h2 Recently active + +gamelist(active_games, true) + + if finished_games.length > 0 + h2 Recently finished + +gamelist(finished_games, true) diff --git a/views/tm_seed.pug b/views/tm_seed.pug index 45659c5..abf02c1 100644 --- a/views/tm_seed.pug +++ b/views/tm_seed.pug @@ -67,11 +67,11 @@ html if user if queue.find(p => p.user_id === user.user_id) - form(method="post" action="/api/tm/withdraw/" + seed.seed_id + "/" + (ix+1)) + form(method="post" action="/tm/withdraw/" + seed.seed_id + "/" + (ix+1)) button(disabled) Register button(type="submit") Withdraw else if may_register && may_join_seed_level(user.user_id, seed.seed_id, ix+1) - form(method="post" action="/api/tm/register/" + seed.seed_id + "/" + (ix+1)) + form(method="post" action="/tm/register/" + seed.seed_id + "/" + (ix+1)) button(type="submit") Register button(disabled) Withdraw else @@ -81,7 +81,7 @@ html if user.user_id === 1 if queue.length >= seed.pool_size - form(method="post" action="/api/tm/start/" + seed.seed_id + "/" + (ix+1)) + form(method="post" action="/tm/start/" + seed.seed_id + "/" + (ix+1)) button(type="submit") Start else p Login or sign up to register. diff --git a/views/user.pug b/views/user.pug index c3e8925..b5859a2 100644 --- a/views/user.pug +++ b/views/user.pug @@ -24,7 +24,7 @@ html h1= who.name if who.about - p.about= who.about + p.box= who.about p Member since #{human_date(who.ctime)}. p Last seen #{human_date(who.atime)}. @@ -42,37 +42,7 @@ html br a(href="/contacts/add-enemy/"+who.name) Add to blacklist - if (who.move_time_mean !== null) - h3 Response time - div Average response time: #{format_minutes(who.move_time_mean)} - if (who.move_time_q2 !== null) - div Median response time: #{format_minutes(who.move_time_q2)} - if (who.move_time_q1 !== null && who.move_time_q2 !== null) - div Middle half of response times: #{format_minutes(who.move_time_q1)} to #{format_minutes(who.move_time_q3)} - - h3 Timeouts - div Total number of timeouts: #{who.timeout_total} - div Games completed since last timeout: #{who.games_since_timeout} - - if ratings.length > 0 - h3 Most played games - table - thead - tr - th Title - th Count - th Last played - if user && user.user_id === 1 - th Elo - tbody - each row in ratings - tr - td - a.black(href="/" + row.title_id)= row.title_name - td.r= row.count - td.r= row.last - if user && user.user_id === 1 - td.r= row.rating + +userstats(who, ratings) +tourlist(null, active_pools, finished_pools) diff --git a/views/user_stats.pug b/views/user_stats.pug deleted file mode 100644 index 3b201ef..0000000 --- a/views/user_stats.pug +++ /dev/null @@ -1,53 +0,0 @@ -//- vim:ts=4:sw=4: -- let all_won = 0 -- let all_total = 0 -doctype html -html - head - include head - title Statistics for #{who.name} - body - include header - article - h1 Statistics for #{who.name} - - table.striped - thead - tr - th Title - th Scenario - th Role - th.r Played - th.r Won - tbody - each row in stats - tr - - all_won += row.won - - all_total += row.total - td= row.title_name - td= row.scenario - td= row.role - td.r= row.total - td.r= Math.round(row.won*100/row.total) + "%" - tfoot - tr - td Overall - td - td - td.r= all_total - td.r= Math.round(all_won*100/all_total) + "%" - - table.striped - thead - tr - th Title - th.r Rating - th.r Plays - th.r Last played - tbody - each row in ratings - tr - td= row.title_name - td.r= row.rating - td.r= row.count - td.r= row.last diff --git a/views/verify_mail.pug b/views/verify_mail.pug deleted file mode 100644 index 01a2e82..0000000 --- a/views/verify_mail.pug +++ /dev/null @@ -1,21 +0,0 @@ -//- vim:ts=4:sw=4: -doctype html -html - head - include head - title Verify mail - body - include header - article - h1 Verify mail - if flash - p.error= flash - - form(method="post" action="/verify-mail") - p A token has been sent to #{user.mail}. - p - label Enter the token here: - br - input(type="text" name="token" size=32 value=token style="font-family:monospace" required) - p - button(type="submit") Verify diff --git a/views/webhook.pug b/views/webhook.pug deleted file mode 100644 index 20d20ac..0000000 --- a/views/webhook.pug +++ /dev/null @@ -1,68 +0,0 @@ -//- vim:ts=4:sw=4: -doctype html -html(lang="en") - head - include head - title Webhook - body - include header - article - - h1 Webhook - - - var url = webhook && webhook.url || "" - - var format = webhook && webhook.format || "" - - var prefix = webhook && webhook.prefix || "" - - form(action="/api/webhook/update" method="post") - if webhook && webhook.error - p.error ERROR: #{webhook.error} - p Webhook URL: - br - input#url(type="text" name="url" size=120 placeholder="https://discord.com/api/webhooks/..." value=url required) - p Webhook format: - br - input#format(type="text" name="format" size=40 placeholder="content" value=format) - - p Message prefix: - br - input#prefix(type="text" name="prefix" size=40 placeholder="<@123456789>" value=prefix) - - if webhook - button(type="submit") Update - else - button(type="submit") Create - - if webhook - form(action="/api/webhook/delete" method="post") - button(type="submit") Delete - - h2 Discord Notifications - - p You can send notifications to a given channel on a Discord server. - - ol - li Create your own server or use an existing server where you have administrator privileges. - li Get the webhook URL for the Discord channel and enter it into the Webhook URL field. - li Enter "content" into the Webhook format field. - li Find your Discord User ID. This is not your username, it is a number. - li Enter your Discord User ID into the Message prefix field as "<@12345>". - - h2 Slack Notifications - - p You can send notifications to a Slack workspace. - - ol - li Join or set up a Slack workspace with a webhook integration. - li Find the Webhook URL and enter it into the Webhook URL field. - li Enter "text" into the Webhook format field. - li Find your Slack User ID. This is a number with "U" in front of it. - li Enter your Slack User ID into the Message prefix field as "<@U12345>". - - h2 Custom Notifications - - p. - You can integrate with any server that accepts inbound webhooks by setting the webhook URL to the appropriate endpoint. - If the format field is blank, the payload is sent as plain text. - Otherwise, the payload is a JSON object where the format field specifies which JSON property holds the message. - Use "content" for Discord and "text" for Slack. -- cgit v1.2.3