locales and start on logged in page
This commit is contained in:
parent
664020ff37
commit
18e4d29063
9 changed files with 191 additions and 43 deletions
|
@ -1,6 +1,6 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
|
|
||||||
<html>
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<title><?php
|
<title><?php
|
||||||
if ($title) {
|
if ($title) {
|
||||||
|
@ -31,4 +31,3 @@
|
||||||
echo "<div class=\"err\">$err<div></div></div>";
|
echo "<div class=\"err\">$err<div></div></div>";
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// site config
|
// site config
|
||||||
$site_name = "Todo List Manager";
|
$site_name = "Todo List Manager";
|
||||||
$signups = "invite"; // true, false, "invite" - treats it as true if no users currently exist, invite requires an admin to invite the user
|
$signups = "invite"; // true, false, "invite" - treats it as true if no users currently exist, invite requires an admin to invite the user
|
||||||
|
$language = "en-US"; // an item from the lang folder. exclude the ".json"
|
||||||
|
|
||||||
$admin_users = array(
|
$admin_users = array(
|
||||||
// "username1", "username2", ...
|
// "username1", "username2", ...
|
||||||
|
@ -20,6 +21,8 @@ $db = pg_connect($db_info);
|
||||||
|
|
||||||
// default schema
|
// default schema
|
||||||
// DON'T CHANGE THIS UNLESS YOU KNOW WHAT YOU'RE DOING!!!
|
// DON'T CHANGE THIS UNLESS YOU KNOW WHAT YOU'RE DOING!!!
|
||||||
|
$lang = json_decode(file_get_contents("lang/$language.json"), true);
|
||||||
|
$default_format = "For %C<b>%t</b>%c - %d";
|
||||||
$default_schema = array(
|
$default_schema = array(
|
||||||
"general" => array(
|
"general" => array(
|
||||||
"name" => "General",
|
"name" => "General",
|
||||||
|
@ -27,7 +30,7 @@ $default_schema = array(
|
||||||
"items" => array(
|
"items" => array(
|
||||||
"general" => array(
|
"general" => array(
|
||||||
"name" => "",
|
"name" => "",
|
||||||
"display_format" => "For <b>%d</b> - %c"
|
"display_format" => "For %C<b>%t</b>%c - %d"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
19
css/base.css
19
css/base.css
|
@ -33,7 +33,12 @@ body {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
h3 {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
input,
|
||||||
|
select {
|
||||||
background-color: var(--input-background);
|
background-color: var(--input-background);
|
||||||
color: var(--color);
|
color: var(--color);
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
|
@ -42,7 +47,8 @@ input {
|
||||||
margin: 2px;
|
margin: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
input:focus {
|
input:focus,
|
||||||
|
select:focus {
|
||||||
outline: 2px solid var(--subtext);
|
outline: 2px solid var(--subtext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,6 +69,15 @@ i {
|
||||||
color: var(--subtext);
|
color: var(--subtext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
margin: 0;
|
||||||
|
padding-left: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
.err {
|
.err {
|
||||||
color: var(--red);
|
color: var(--red);
|
||||||
border: 2px dashed var(--red);
|
border: 2px dashed var(--red);
|
||||||
|
|
|
@ -28,7 +28,7 @@ function is_logged_in(): false | array {
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($user_object && get_token($user_object[0]["username"], $user_object[0]["password_hash"]) === $token) {
|
if ($user_object && get_token($user_object[0]["username"], $user_object[0]["password_hash"]) === $token) {
|
||||||
return $user_object;
|
return $user_object[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
100
index.php
100
index.php
|
@ -1,19 +1,109 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
include "config.php";
|
include "config.php";
|
||||||
include "helper.php";
|
include "helper.php";
|
||||||
include "boilerplate/head.php";
|
include "boilerplate/head.php";
|
||||||
|
|
||||||
echo(is_logged_in());
|
$user = is_logged_in();
|
||||||
?>
|
|
||||||
|
|
||||||
<a href="login.php">Log In</a>
|
if ($user === false) {
|
||||||
|
echo "<a href=\"login.php\">{$lang['account']['log_in']}</a>";
|
||||||
|
|
||||||
<?php
|
|
||||||
$q = "SELECT count(*) FROM users LIMIT 1;";
|
$q = "SELECT count(*) FROM users LIMIT 1;";
|
||||||
|
|
||||||
if ($signups !== false || ($signups === false && pg_fetch_array(pg_query($db, $q))["count"] !== 0)) {
|
if ($signups !== false || ($signups === false && pg_fetch_array(pg_query($db, $q))["count"] !== 0)) {
|
||||||
echo "- <a href=\"signup.php\">Sign Up</a>";
|
echo " - <a href=\"signup.php\">{$lang['account']['sign_up']}</a>";
|
||||||
}
|
}
|
||||||
|
|
||||||
include "boilerplate/foot.php";
|
include "boilerplate/foot.php";
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$select_options = "";
|
||||||
|
$todo_list = "";
|
||||||
|
|
||||||
|
$q = "SELECT * FROM section WHERE users='{$user['id']}' ORDER BY LOWER(name) ASC;";
|
||||||
|
$sections = pg_fetch_all(pg_query($db, $q));
|
||||||
|
|
||||||
|
foreach ($sections as $section) {
|
||||||
|
$q = "SELECT * FROM row WHERE section='{$section['id']}' ORDER BY LOWER(name) ASC;";
|
||||||
|
$rows = pg_fetch_all(pg_query($db, $q));
|
||||||
|
$show_subtitle = $section["show_subtitle"] === "t";
|
||||||
|
$enable_optgroup = $show_subtitle || count($rows) !== 1;
|
||||||
|
|
||||||
|
$todo_list .= "<h3>" . htmlspecialchars($section["name"]) . "</h3>";
|
||||||
|
|
||||||
|
if ($enable_optgroup) {
|
||||||
|
$select_options .= "<optgroup label=\"" . htmlspecialchars($section["name"]) . "\">";
|
||||||
|
}
|
||||||
|
|
||||||
|
$first = true;
|
||||||
|
foreach ($rows as $row) {
|
||||||
|
$select_options .= "<option value=\"{$section['id']}-{$row['id']}\">";
|
||||||
|
|
||||||
|
if ($first && !$show_subtitle) {
|
||||||
|
$select_options .= htmlspecialchars($section["name"]);
|
||||||
|
} else {
|
||||||
|
$select_options .= htmlspecialchars($row["name"]);
|
||||||
|
$todo_list .= "<strong>" . htmlspecialchars($row["name"]) . "</strong>";
|
||||||
|
}
|
||||||
|
|
||||||
|
$q = "SELECT * FROM item WHERE row='{$row['id']}' ORDER BY date ASC, LOWER(description) ASC;";
|
||||||
|
$items = pg_fetch_all(pg_query($db, $q));
|
||||||
|
$todo_list .= "<ul>";
|
||||||
|
|
||||||
|
if (count($items) === 0) {
|
||||||
|
$todo_list .= "<li><i>{$lang['list']['none']}</i></li>";
|
||||||
|
} else {
|
||||||
|
foreach ($items as $item) {
|
||||||
|
$todo_list .= "<li>" . str_replace("%d", htmlspecialchars($item["description"]), $row["display_format"]) . "</li>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$todo_list .= "</ul>";
|
||||||
|
$select_options .= "</option>";
|
||||||
|
$first = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($enable_optgroup) {
|
||||||
|
$select_options .= "</optgroup>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div id="container">
|
||||||
|
<h2><?php echo $lang["add"]["title"]; ?></h2>
|
||||||
|
<form method="POST">
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td class="right"><label for="section"><?php echo $lang["add"]["section"]; ?></label></td>
|
||||||
|
<td>
|
||||||
|
<select required id="section" name="section">
|
||||||
|
<?php echo $select_options; ?>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="right"><label for="date"><?php echo $lang["add"]["date"]; ?></label></td>
|
||||||
|
<td><input type="date" name="date" id="date" required></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="right"><label for="description"><?php echo $lang["add"]["description"]; ?></label></td>
|
||||||
|
<td><input autofocus maxlength="256" placeholder="<?php echo $lang["add"]["description_placeholder"]; ?>" name="description" id="description" required></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td><input type="submit" value="<?php echo $lang["add"]["button"]; ?>"></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<h2><?php echo $lang["list"]["title"]; ?></h2>
|
||||||
|
<?php echo $todo_list; ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
include "boilerplate/foot.php";
|
||||||
?>
|
?>
|
||||||
|
|
36
lang/en-US.json
Normal file
36
lang/en-US.json
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
{
|
||||||
|
"account": {
|
||||||
|
"errors": {
|
||||||
|
"bad_request": "Bad request",
|
||||||
|
"username_length": "Username must be between 1 and 64 characters",
|
||||||
|
"username_characters": "Username can only include a-z, 0-9, _, and -",
|
||||||
|
"user_not_found": "User '%u' not found",
|
||||||
|
"user_exists": "User '%u' already exists",
|
||||||
|
"incorrect_password": "Incorrect password",
|
||||||
|
"password_match": "Passwords don't match"
|
||||||
|
},
|
||||||
|
|
||||||
|
"log_in": "Log In",
|
||||||
|
"log_in_instead": "Log in instead?",
|
||||||
|
"sign_up": "Sign Up",
|
||||||
|
"sign_up_instead": "Sign up instead?",
|
||||||
|
"username": "Username",
|
||||||
|
"password": "Password",
|
||||||
|
"verify": "Verify password"
|
||||||
|
},
|
||||||
|
|
||||||
|
"add": {
|
||||||
|
"title": "Add Item",
|
||||||
|
"section": "Section:",
|
||||||
|
"date": "Date:",
|
||||||
|
"description": "Description:",
|
||||||
|
"description_placeholder": "Important thing",
|
||||||
|
"button": "Add"
|
||||||
|
},
|
||||||
|
|
||||||
|
"list": {
|
||||||
|
"title": "Current Todo List",
|
||||||
|
"remove": "Completed",
|
||||||
|
"none": "None"
|
||||||
|
}
|
||||||
|
}
|
20
login.php
20
login.php
|
@ -15,18 +15,18 @@
|
||||||
$p = $_POST["password"];
|
$p = $_POST["password"];
|
||||||
|
|
||||||
if (!($u && $p)) {
|
if (!($u && $p)) {
|
||||||
$err = "Bad request, missing username or password parameter";
|
$err = $lang["account"]["errors"]["bad_request"];
|
||||||
} else if (strlen($u) > 64 || strlen($u) === 0) {
|
} else if (strlen($u) > 64 || strlen($u) === 0) {
|
||||||
$err = "Username must be 1-64 chars";
|
$err = $lang["account"]["errors"]["username_length"];
|
||||||
} else if (!preg_match("/^[a-z0-9_-]{1,64}$/", $u)) {
|
} else if (!preg_match("/^[a-z0-9_-]{1,64}$/", $u)) {
|
||||||
$err = "Username can only include a-z, 0-9, _, and -";
|
$err = $lang["account"]["errors"]["username_characters"];
|
||||||
} else {
|
} else {
|
||||||
$query = "SELECT password_hash FROM users WHERE username='$u' LIMIT 1;";
|
$query = "SELECT password_hash FROM users WHERE username='$u' LIMIT 1;";
|
||||||
|
|
||||||
$response = pg_query($db, $query);
|
$response = pg_query($db, $query);
|
||||||
|
|
||||||
if (pg_num_rows($response) === 0) {
|
if (pg_num_rows($response) === 0) {
|
||||||
$err = "User '" . htmlspecialchars($u) . "' not found";
|
$err = str_replace("%u", htmlspecialchars($u), $lang["account"]["errors"]["user_not_found"]);
|
||||||
} else {
|
} else {
|
||||||
$user = pg_fetch_array($response);
|
$user = pg_fetch_array($response);
|
||||||
if (password_verify($p, $user["password_hash"])) {
|
if (password_verify($p, $user["password_hash"])) {
|
||||||
|
@ -38,27 +38,27 @@
|
||||||
header("Location: index.php");
|
header("Location: index.php");
|
||||||
exit();
|
exit();
|
||||||
} else {
|
} else {
|
||||||
$err = "Incorrect password";
|
$err = $lang["account"]["errors"]["incorrect_password"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$title = "Log In";
|
$title = $lang["account"]["log_in"];
|
||||||
include "boilerplate/head.php";
|
include "boilerplate/head.php";
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
<div><input placeholder="Username" name="username" value="<?php echo htmlspecialchars($u); ?>" maxlength="64" required></div>
|
<div><input placeholder="<?php echo $lang["account"]["username"]; ?>" name="username" value="<?php echo htmlspecialchars($u); ?>" maxlength="64" required></div>
|
||||||
<div><input placeholder="Password" name="password" type="password" value="<?php echo htmlspecialchars($p); ?>" required></div>
|
<div><input placeholder="<?php echo $lang["account"]["password"]; ?>" name="password" type="password" value="<?php echo htmlspecialchars($p); ?>" required></div>
|
||||||
<div><input type="submit" value="Log in"></div>
|
<div><input type="submit" value="<?php echo $lang["account"]["log_in"]; ?>"></div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
$q = "SELECT count(*) FROM users LIMIT 1;";
|
$q = "SELECT count(*) FROM users LIMIT 1;";
|
||||||
|
|
||||||
if ($signups !== false || ($signups === false && pg_fetch_array(pg_query($db, $q))["count"] !== 0)) {
|
if ($signups !== false || ($signups === false && pg_fetch_array(pg_query($db, $q))["count"] !== 0)) {
|
||||||
echo "<p><a href=\"signup.php\">Sign up instead?</a></p>";
|
echo "<p><a href=\"signup.php\">{$lang['account']['sign_up_instead']}</a></p>";
|
||||||
}
|
}
|
||||||
|
|
||||||
include "boilerplate/foot.php";
|
include "boilerplate/foot.php";
|
||||||
|
|
|
@ -6,7 +6,10 @@ $queries = array(
|
||||||
"CREATE TABLE IF NOT EXISTS users (
|
"CREATE TABLE IF NOT EXISTS users (
|
||||||
id VARCHAR(64) PRIMARY KEY,
|
id VARCHAR(64) PRIMARY KEY,
|
||||||
username VARCHAR(64) UNIQUE NOT NULL,
|
username VARCHAR(64) UNIQUE NOT NULL,
|
||||||
password_hash VARCHAR(256) NOT NULL
|
password_hash VARCHAR(256) NOT NULL,
|
||||||
|
enable_colors BOOLEAN NOT NULL,
|
||||||
|
yellow_threshold INT NOT NULL,
|
||||||
|
gray_threshold INT NOT NULL
|
||||||
);",
|
);",
|
||||||
"CREATE TABLE IF NOT EXISTS section (
|
"CREATE TABLE IF NOT EXISTS section (
|
||||||
id VARCHAR(64) PRIMARY KEY,
|
id VARCHAR(64) PRIMARY KEY,
|
||||||
|
@ -17,8 +20,8 @@ $queries = array(
|
||||||
"CREATE TABLE IF NOT EXISTS row (
|
"CREATE TABLE IF NOT EXISTS row (
|
||||||
id VARCHAR(64) PRIMARY KEY,
|
id VARCHAR(64) PRIMARY KEY,
|
||||||
section VARCHAR(64) NOT NULL REFERENCES section(id),
|
section VARCHAR(64) NOT NULL REFERENCES section(id),
|
||||||
name VARCHAR(128),
|
name VARCHAR(128), -- ignored if first item and show_subtitle is enabled
|
||||||
display_format VARCHAR(128) NOT NULL -- %d - date, %c - description
|
display_format VARCHAR(128) NOT NULL -- %t - date, %d - description, %C - start color, %c - end color
|
||||||
);",
|
);",
|
||||||
"CREATE TABLE IF NOT EXISTS item (
|
"CREATE TABLE IF NOT EXISTS item (
|
||||||
id VARCHAR(64) PRIMARY KEY,
|
id VARCHAR(64) PRIMARY KEY,
|
||||||
|
|
30
signup.php
30
signup.php
|
@ -16,13 +16,13 @@
|
||||||
$v = $_POST["verify"];
|
$v = $_POST["verify"];
|
||||||
|
|
||||||
if ($v != $p) {
|
if ($v != $p) {
|
||||||
$err = "Passwords don't match";
|
$err = $lang["account"]["errors"]["password_match"];
|
||||||
} else if (!($u && $p && $v)) {
|
} else if (!($u && $p && $v)) {
|
||||||
$err = "Bad request, missing username, password, or verify parameter";
|
$err = $lang["account"]["errors"]["bad_request"];
|
||||||
} else if (strlen($u) > 64 || strlen($u) === 0) {
|
} else if (strlen($u) > 64 || strlen($u) === 0) {
|
||||||
$err = "Username must be 1-64 chars";
|
$err = $lang["account"]["errors"]["username_length"];
|
||||||
} else if (!preg_match("/^[a-z0-9_-]{1,64}$/", $u)) {
|
} else if (!preg_match("/^[a-z0-9_-]{1,64}$/", $u)) {
|
||||||
$err = "Username can only include a-z, 0-9, _, and -";
|
$err = $lang["account"]["errors"]["username_characters"];
|
||||||
} else {
|
} else {
|
||||||
$query = "SELECT count(*) FROM users WHERE username='$u' LIMIT 1;";
|
$query = "SELECT count(*) FROM users WHERE username='$u' LIMIT 1;";
|
||||||
|
|
||||||
|
@ -35,7 +35,10 @@
|
||||||
$user_parameters = array(
|
$user_parameters = array(
|
||||||
"id" => $user_id,
|
"id" => $user_id,
|
||||||
"username" => $u,
|
"username" => $u,
|
||||||
"password_hash" => $pw_hash
|
"password_hash" => $pw_hash,
|
||||||
|
"enable_colors" => true,
|
||||||
|
"yellow_threshold" => 2,
|
||||||
|
"gray_threshold" => 60
|
||||||
);
|
);
|
||||||
|
|
||||||
pg_insert($db, "users", $user_parameters);
|
pg_insert($db, "users", $user_parameters);
|
||||||
|
@ -66,28 +69,27 @@
|
||||||
|
|
||||||
$token = get_token($u, $pw_hash);
|
$token = get_token($u, $pw_hash);
|
||||||
setcookie(
|
setcookie(
|
||||||
"token",
|
"token", $token,
|
||||||
$token,
|
|
||||||
time() + 60 * 60 * 24 * 30 * 265 // 1 year from now
|
time() + 60 * 60 * 24 * 30 * 265 // 1 year from now
|
||||||
);
|
);
|
||||||
header("Location: index.php");
|
header("Location: index.php");
|
||||||
exit();
|
exit();
|
||||||
} else {
|
} else {
|
||||||
$err = "User '" . htmlspecialchars($u) . "' already exists";
|
$err = str_replace("%u", htmlspecialchars($u), $lang["account"]["errors"]["user_exists"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$title = "Sign Up";
|
$title = $lang["account"]["sign_up"];
|
||||||
include "boilerplate/head.php";
|
include "boilerplate/head.php";
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
<div><input placeholder="Username" name="username" value="<?php echo htmlspecialchars($u); ?>" maxlength="64" required></div>
|
<div><input placeholder="<?php echo $lang["account"]["username"]; ?>" name="username" value="<?php echo htmlspecialchars($u); ?>" maxlength="64" required></div>
|
||||||
<div><input placeholder="Password" name="password" type="password" value="<?php echo htmlspecialchars($p); ?>" required></div>
|
<div><input placeholder="<?php echo $lang["account"]["password"]; ?>" name="password" type="password" value="<?php echo htmlspecialchars($p); ?>" required></div>
|
||||||
<div><input placeholder="Verify Password" name="verify" type="password" required></div>
|
<div><input placeholder="<?php echo $lang["account"]["verify"]; ?>" name="verify" type="password" required></div>
|
||||||
<div><input type="submit" value="Sign Up"></div>
|
<div><input type="submit" value="<?php echo $lang["account"]["sign_up"]; ?>"></div>
|
||||||
<p><a href="login.php">Log in instead?</a></p>
|
<p><a href="login.php"><?php echo $lang["account"]["log_in_instead"]; ?></a></p>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
|
|
Loading…
Reference in a new issue