sync, implemented sort, viewing user pages & articles written, updating db
This commit is contained in:
+39
-3
@@ -6,14 +6,50 @@ include_once 'components/head.php';
|
|||||||
|
|
||||||
include_once 'functions/article_functions.php';
|
include_once 'functions/article_functions.php';
|
||||||
|
|
||||||
// TODO: Move to a grid, where the left hand column is either a search and filtering system, or...Table of Contents?
|
|
||||||
|
|
||||||
// Default view, it'll show articles by recency
|
// Default view, it'll show articles by recency
|
||||||
if (!isset($_GET['article_id']) && !isset($_GET['tag']) && !isset($_GET['author_id'])) {
|
if (!isset($_GET['article_id']) && !isset($_GET['tag']) && !isset($_GET['author_id'])) {
|
||||||
$ids = article_ids_by_recency();
|
$filters = '
|
||||||
|
<form method="get">
|
||||||
|
<div class="row no_margin">
|
||||||
|
';
|
||||||
|
|
||||||
|
if (!isset($_GET['sort']) || $_GET['sort'] == 'newest') {
|
||||||
|
$ids = article_ids_by_newest();
|
||||||
|
$filters .= '
|
||||||
|
<p>Newest - Oldest</p>
|
||||||
|
<label for="recency_desc"><i class="nf nf-md-sort_clock_descending_outline"></i>
|
||||||
|
<input id="recency_desc" type="radio" name="sort" value="oldest" onclick="this.form.submit()">
|
||||||
|
</label>
|
||||||
|
';
|
||||||
|
} else if ($_GET['sort'] == 'oldest') {
|
||||||
|
$ids = article_ids_by_oldest();
|
||||||
|
$filters .= '
|
||||||
|
<p>Oldest - Newest</p>
|
||||||
|
<label for="recency_asc"><i class="nf nf-md-sort_clock_ascending_outline"></i>
|
||||||
|
<input id="recency_asc" type="radio" name="sort" value="newest" onclick="this.form.submit()">
|
||||||
|
</label>
|
||||||
|
';
|
||||||
|
}
|
||||||
|
|
||||||
|
$filters .= '
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
';
|
||||||
|
|
||||||
|
|
||||||
|
echo '
|
||||||
|
<div class="article_cards_grid">
|
||||||
|
<div class="article_filters">
|
||||||
|
' . $filters . '
|
||||||
|
</div>
|
||||||
|
<div class="article_cards">
|
||||||
|
';
|
||||||
foreach ($ids as $id)
|
foreach ($ids as $id)
|
||||||
echo article_card($id);
|
echo article_card($id);
|
||||||
|
echo '
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
';
|
||||||
} else if (isset($_GET['article_id'])) {
|
} else if (isset($_GET['article_id'])) {
|
||||||
increment_read_counter($_GET['article_id']);
|
increment_read_counter($_GET['article_id']);
|
||||||
echo article_page_from_markdown($_GET['article_id']);
|
echo article_page_from_markdown($_GET['article_id']);
|
||||||
|
|||||||
+5
-4
@@ -4,17 +4,18 @@
|
|||||||
<head>
|
<head>
|
||||||
<link href="css/base.css" rel="stylesheet" type="text/css">
|
<link href="css/base.css" rel="stylesheet" type="text/css">
|
||||||
<link rel="stylesheet" href="https://nerdfonts.com/assets/css/webfont.css">
|
<link rel="stylesheet" href="https://nerdfonts.com/assets/css/webfont.css">
|
||||||
|
<link rel="icon" type="image/x-icon" href="data/vintagecoding-favicon.png">
|
||||||
<?php
|
<?php
|
||||||
if ($_SESSION['theme'] == 'dark') {
|
if ($_SESSION['theme'] == 'dark') {
|
||||||
echo '
|
echo '
|
||||||
<link href="css/dark.css" rel="stylesheet" type="text/css">
|
<link href="css/dark.css" rel="stylesheet" type="text/css">
|
||||||
';
|
';
|
||||||
} elseif ($_SESSION['theme'] == 'light') {
|
} elseif ($_SESSION['theme'] == 'light') {
|
||||||
echo '
|
echo '
|
||||||
<link href="css/light.css" rel="stylesheet" type="text/css">
|
<link href="css/light.css" rel="stylesheet" type="text/css">
|
||||||
';
|
';
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ $nav = '
|
|||||||
<div class="site_navigation">
|
<div class="site_navigation">
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="/index.php"' . ($current_page == '/index.php' ? ' class="underline"' : '') . '>Home</a></li>
|
<li><a href="/index.php"' . ($current_page == '/index.php' ? ' class="underline"' : '') . '>Home</a></li>
|
||||||
<li><a href="/articles.php"' . ($current_page == '/articles.php' ? ' class="underline"' : '') . '>Articles</a></li>
|
<li><a href="/articles.php?sort=newest"' . ($current_page == '/articles.php' ? ' class="underline"' : '') . '>Articles</a></li>
|
||||||
';
|
';
|
||||||
|
|
||||||
if (isset($_COOKIE['role_id']) && $_COOKIE['role_id'] <= 2) {
|
if (isset($_COOKIE['role_id']) && $_COOKIE['role_id'] <= 2) {
|
||||||
|
|||||||
+2
-1
@@ -4,7 +4,7 @@ require_once 'functions/functions.php';
|
|||||||
include_once 'functions/article_functions.php';
|
include_once 'functions/article_functions.php';
|
||||||
|
|
||||||
if (!empty($_POST)) {
|
if (!empty($_POST)) {
|
||||||
$id = create_article($_COOKIE['user_id'], $_POST['title'], $_POST['excerpt'], $_POST['tags'], $_POST['markdown']);
|
$id = create_article($_COOKIE['user_id'], $_POST['title'], $_POST['excerpt'], (isset($_POST['tags']) ? $_POST['tags'] : []), $_POST['markdown']);
|
||||||
header('Location: articles.php?article_id=' . $id);
|
header('Location: articles.php?article_id=' . $id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -14,6 +14,7 @@ if (!isset($_COOKIE['role_id']) || $_COOKIE['role_id'] == 4)
|
|||||||
include_once 'components/head.php';
|
include_once 'components/head.php';
|
||||||
|
|
||||||
echo form();
|
echo form();
|
||||||
|
|
||||||
include_once 'components/foot.php';
|
include_once 'components/foot.php';
|
||||||
|
|
||||||
function form()
|
function form()
|
||||||
|
|||||||
+63
-11
@@ -60,12 +60,6 @@ label,
|
|||||||
font-size: 1vw;
|
font-size: 1vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
p::after {
|
|
||||||
content: "";
|
|
||||||
display: inline-block;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
small {
|
small {
|
||||||
font-size: .75vw;
|
font-size: .75vw;
|
||||||
}
|
}
|
||||||
@@ -171,9 +165,9 @@ code {
|
|||||||
.view_card {
|
.view_card {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
margin-top: 50px;
|
margin-top: 50px;
|
||||||
|
width: 70%;
|
||||||
padding: 18px;
|
padding: 18px;
|
||||||
height: max-content;
|
height: max-content;
|
||||||
width: 70%;
|
|
||||||
border-radius: 18px;
|
border-radius: 18px;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -184,6 +178,11 @@ code {
|
|||||||
transition-duration: 1s;
|
transition-duration: 1s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.article_card {
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
.form_card {
|
.form_card {
|
||||||
width: 50%;
|
width: 50%;
|
||||||
}
|
}
|
||||||
@@ -292,7 +291,8 @@ table tr td label {
|
|||||||
text-decoration-color: orange;
|
text-decoration-color: orange;
|
||||||
}
|
}
|
||||||
|
|
||||||
#theme-toggle {
|
#theme-toggle,
|
||||||
|
label i {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
border: none;
|
border: none;
|
||||||
@@ -300,16 +300,25 @@ table tr td label {
|
|||||||
font-size: 1.5vw;
|
font-size: 1.5vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
#theme-toggle * {
|
#theme-toggle *,
|
||||||
|
label i {
|
||||||
transition-duration: 500ms;
|
transition-duration: 500ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
#theme-toggle *:hover {
|
#theme-toggle *:hover,
|
||||||
|
label i:hover {
|
||||||
color: orange;
|
color: orange;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
label i {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
font-size: 1.5vw;
|
||||||
|
transition-duration: 500ms;
|
||||||
|
}
|
||||||
|
|
||||||
.article {
|
.article {
|
||||||
width: 50%;
|
width: 60%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -589,3 +598,46 @@ input[type="file"] {
|
|||||||
[data-href] {
|
[data-href] {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.article_cards_grid {
|
||||||
|
width: 70%;
|
||||||
|
margin: 0 auto;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.article_grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 15% 85%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.article_toc {
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tooltip container */
|
||||||
|
.tooltip {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
border-bottom: 1px dotted black;
|
||||||
|
/* If you want dots under the hoverable text */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tooltip text */
|
||||||
|
.tooltip .tooltiptext {
|
||||||
|
visibility: hidden;
|
||||||
|
width: 120px;
|
||||||
|
background-color: black;
|
||||||
|
color: #fff;
|
||||||
|
text-align: center;
|
||||||
|
padding: 5px 0;
|
||||||
|
border-radius: 6px;
|
||||||
|
|
||||||
|
/* Position the tooltip text - see examples below! */
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Show the tooltip text when you mouse over the tooltip container */
|
||||||
|
.tooltip:hover .tooltiptext {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once 'db_functions.php';
|
require_once 'db_functions.php';
|
||||||
|
require_once 'article_functions.php';
|
||||||
|
|
||||||
function user_id_exists($user_id)
|
function user_id_exists($user_id)
|
||||||
{
|
{
|
||||||
@@ -175,12 +176,13 @@ function create_user($username, $email, $password, $verify_password, $role_id, $
|
|||||||
|
|
||||||
crop_image($upload['profile_picture']['tmp_name'], $x, $y, $crop_size, $crop_size);
|
crop_image($upload['profile_picture']['tmp_name'], $x, $y, $crop_size, $crop_size);
|
||||||
$target = upload($upload['profile_picture'], $_ENV['PROFILE_IMAGES_FQ_PATH'], $id);
|
$target = upload($upload['profile_picture'], $_ENV['PROFILE_IMAGES_FQ_PATH'], $id);
|
||||||
|
} else {
|
||||||
|
$target = 'default-profile.png';
|
||||||
}
|
}
|
||||||
|
|
||||||
$conn = get_connection();
|
$conn = get_connection();
|
||||||
$stmt = $conn->prepare('INSERT INTO user (user_id, username, email, password_hash, role_id, profile_picture) VALUES (?, ?, ?, ?, ?, ?)');
|
$stmt = $conn->prepare('INSERT INTO user (user_id, username, email, password_hash, role_id, profile_picture) VALUES (?, ?, ?, ?, ?, ?)');
|
||||||
$asdf = (isset($target) ? $target : null);
|
$stmt->bind_param('isssis', $id, $username, $email, $password_hash, $role_id, $target);
|
||||||
$stmt->bind_param('isssis', $id, $username, $email, $password_hash, $role_id, $asdf);
|
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -492,9 +494,6 @@ function delete_account($user_id, $password = null, $verify_password = null)
|
|||||||
|
|
||||||
function user_view($user_id)
|
function user_view($user_id)
|
||||||
{
|
{
|
||||||
if (!isset($_COOKIE['role_id']) || ($_COOKIE['role_id'] > 2 && $_COOKIE['user_id'] != $user_id))
|
|
||||||
header('Location: articles.php');
|
|
||||||
|
|
||||||
$conn = get_connection();
|
$conn = get_connection();
|
||||||
$stmt = $conn->prepare('SELECT user_id, username, email, role_id, created_at, last_active, is_active, profile_picture FROM user WHERE user_id = ?');
|
$stmt = $conn->prepare('SELECT user_id, username, email, role_id, created_at, last_active, is_active, profile_picture FROM user WHERE user_id = ?');
|
||||||
$stmt->bind_param('i', $user_id);
|
$stmt->bind_param('i', $user_id);
|
||||||
@@ -513,13 +512,14 @@ function user_view($user_id)
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="line"></div>
|
<div class="line"></div>
|
||||||
<h3>User Actions</h3>
|
|
||||||
';
|
';
|
||||||
|
|
||||||
// TODO: Need to setup an email handler.
|
// TODO: Need to setup an email handler.
|
||||||
// <a class="modal_button underline">Request Role</a>
|
// <a class="modal_button underline">Request Role</a>
|
||||||
// <div id="request_role_form" class="modal_form">' . request_role_change_form() . '</div>
|
// <div id="request_role_form" class="modal_form">' . request_role_change_form() . '</div>
|
||||||
|
if ((isset($_COOKIE['user_id']) && $_COOKIE['user_id'] == $user_id) || (isset($_COOKIE['role_id']) && $_COOKIE['role_id'] <= 2)) {
|
||||||
$view .= '
|
$view .= '
|
||||||
|
<h3>User Actions</h3>
|
||||||
<div class="user_actions">
|
<div class="user_actions">
|
||||||
<button id="reset_pw_form_button" class="modal_button underline">Reset Password</button>
|
<button id="reset_pw_form_button" class="modal_button underline">Reset Password</button>
|
||||||
<button id="update_email_form_button" class="modal_button underline">Update Email</button>
|
<button id="update_email_form_button" class="modal_button underline">Update Email</button>
|
||||||
@@ -528,8 +528,7 @@ function user_view($user_id)
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="user_actions_modal" class="modal">
|
<div id="user_actions_modal" class="modal">
|
||||||
<div id="modal_content">
|
<div id="modal_content"></div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="display: none;">
|
<div style="display: none;">
|
||||||
@@ -540,6 +539,17 @@ function user_view($user_id)
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
';
|
';
|
||||||
|
} else {
|
||||||
|
$ids = articles_ids_by_author($_GET['user_id']);
|
||||||
|
$view .= '
|
||||||
|
<div class="article_cards">
|
||||||
|
';
|
||||||
|
|
||||||
|
foreach ($ids as $id)
|
||||||
|
$view .= article_card($id);
|
||||||
|
|
||||||
|
$view .= '</div>';
|
||||||
|
}
|
||||||
|
|
||||||
return $view;
|
return $view;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once 'db_functions.php';
|
require_once 'db_functions.php';
|
||||||
|
|
||||||
function article_ids_by_recency()
|
function article_ids_by_newest()
|
||||||
{
|
{
|
||||||
$conn = get_connection();
|
$conn = get_connection();
|
||||||
$results = $conn->query('SELECT article_id FROM article ORDER BY published_at DESC');
|
$results = $conn->query('SELECT article_id FROM article ORDER BY published_at DESC');
|
||||||
@@ -14,6 +14,19 @@ function article_ids_by_recency()
|
|||||||
return $ids;
|
return $ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function article_ids_by_oldest()
|
||||||
|
{
|
||||||
|
$conn = get_connection();
|
||||||
|
$results = $conn->query('SELECT article_id FROM article ORDER BY published_at ASC');
|
||||||
|
|
||||||
|
$ids = [];
|
||||||
|
|
||||||
|
while ($row = $results->fetch_assoc())
|
||||||
|
$ids[] = $row['article_id'];
|
||||||
|
|
||||||
|
return $ids;
|
||||||
|
}
|
||||||
|
|
||||||
function articles_ids_by_author($author_id)
|
function articles_ids_by_author($author_id)
|
||||||
{
|
{
|
||||||
$conn = get_connection();
|
$conn = get_connection();
|
||||||
@@ -77,6 +90,13 @@ function article_page_from_markdown($article_id)
|
|||||||
$markdown = read_file_one_string($_ENV['ARTICLES_FQ_PATH'] . $article_id . '/article.md');
|
$markdown = read_file_one_string($_ENV['ARTICLES_FQ_PATH'] . $article_id . '/article.md');
|
||||||
|
|
||||||
$parsedown = new Parsedown();
|
$parsedown = new Parsedown();
|
||||||
|
$article_content = $parsedown->text($markdown);
|
||||||
|
$article_toc = '';
|
||||||
|
|
||||||
|
$lines = preg_split("/\r\n|\n|\r/", $article_content);
|
||||||
|
foreach ($lines as $line)
|
||||||
|
if (str_contains($line, '<h4>'))
|
||||||
|
$article_toc .= '<p>' . extract_content_from_tag($line, '<h4>', '</h4>') . '</p>';
|
||||||
|
|
||||||
$html = '
|
$html = '
|
||||||
<div class="article">
|
<div class="article">
|
||||||
@@ -91,14 +111,37 @@ function article_page_from_markdown($article_id)
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="line" style="margin-bottom: 15px;"></div>
|
<div class="line" style="margin-bottom: 15px;"></div>
|
||||||
|
<div class="article_grid">
|
||||||
|
<div class="article_toc">
|
||||||
|
' . $article_toc . '
|
||||||
|
</div>
|
||||||
|
<div class="article_content">
|
||||||
|
' . $article_content . '
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
';
|
';
|
||||||
|
|
||||||
$html .= $parsedown->text($markdown);
|
|
||||||
$html .= '</div>';
|
|
||||||
|
|
||||||
return $html;
|
return $html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function article_filters()
|
||||||
|
{
|
||||||
|
$filters = '
|
||||||
|
<form method="get">
|
||||||
|
<label for="recency_desc"><i class="nf nf-md-sort_clock_ascending_outline"></i>
|
||||||
|
<input id="recency_desc" type="radio" name="sort" value="oldest" onclick="this.form.submit()">
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label for="recency_asc"><i class="nf nf-md-sort_clock_descending_outline"></i>
|
||||||
|
<input id="recency_asc" type="radio" name="sort" value="newest" onclick="this.form.submit()">
|
||||||
|
</label>
|
||||||
|
</form>
|
||||||
|
';
|
||||||
|
|
||||||
|
return $filters;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generates cards for a given article.
|
* Generates cards for a given article.
|
||||||
*/
|
*/
|
||||||
@@ -188,6 +231,7 @@ function create_article($author_id, $title, $excerpt, $tags, $markdown_file_cont
|
|||||||
return $id;
|
return $id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function delete_article($article_id)
|
function delete_article($article_id)
|
||||||
{
|
{
|
||||||
$conn = get_connection();
|
$conn = get_connection();
|
||||||
|
|||||||
@@ -128,6 +128,17 @@ function read_file($file_path)
|
|||||||
return $fs;
|
return $fs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function extract_content_from_tag($string, $start, $end)
|
||||||
|
{
|
||||||
|
$ini = strpos($string, $start);
|
||||||
|
if ($ini != 0)
|
||||||
|
return "nope";
|
||||||
|
|
||||||
|
$ini += strlen($start);
|
||||||
|
$len = strpos($string, $end, $ini) - $ini;
|
||||||
|
return substr($string, $ini, $len);
|
||||||
|
}
|
||||||
|
|
||||||
function check_image_upload($target, $filetype, $image)
|
function check_image_upload($target, $filetype, $image)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
+2
-2
@@ -37,7 +37,7 @@ if (isset($_COOKIE['user_id'])) {
|
|||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
$user = $stmt->get_result()->fetch_assoc();
|
$user = $stmt->get_result()->fetch_assoc();
|
||||||
|
|
||||||
$time = time() + 60 * 60 * 1;
|
$time = time() + 60 * 15;
|
||||||
cookies($user, $time);
|
cookies($user, $time);
|
||||||
} else if (isset($_COOKIE['remember_user'])) {
|
} else if (isset($_COOKIE['remember_user'])) {
|
||||||
$conn = get_connection();
|
$conn = get_connection();
|
||||||
@@ -64,7 +64,7 @@ if (isset($_COOKIE['user_id'])) {
|
|||||||
$stmt->bind_param('i', $_COOKIE['user_id']);
|
$stmt->bind_param('i', $_COOKIE['user_id']);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
|
|
||||||
$time = time() + 60 * 60 * 1;
|
$time = time() + 60 * 15;
|
||||||
cookies($user, $time);
|
cookies($user, $time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// Optional: Real-time preview using JavaScript
|
||||||
|
const textarea = document.querySelector('textarea');
|
||||||
|
const preview = document.getElementById('preview');
|
||||||
|
|
||||||
|
textarea.addEventListener('input', function() {
|
||||||
|
fetch('preview.php', { // Create a separate preview.php file for real-time updates
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
},
|
||||||
|
body: 'markdown=' + encodeURIComponent(this.value),
|
||||||
|
})
|
||||||
|
.then(response => response.text())
|
||||||
|
.then(data => {
|
||||||
|
preview.innerHTML = data;
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -21,6 +21,11 @@ CREATE TABLE user (
|
|||||||
last_active TIMESTAMP DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
|
last_active TIMESTAMP DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
|
||||||
is_active BOOLEAN DEFAULT FALSE,
|
is_active BOOLEAN DEFAULT FALSE,
|
||||||
profile_picture VARCHAR(256),
|
profile_picture VARCHAR(256),
|
||||||
|
bio VARCHAR(256),
|
||||||
|
x_username VARCHAR(32),
|
||||||
|
fb_username VARCHAR(32),
|
||||||
|
ig_username VARCHAR(32),
|
||||||
|
website VARCHAR(64),
|
||||||
FOREIGN KEY (role_id) REFERENCES roles (role_id)
|
FOREIGN KEY (role_id) REFERENCES roles (role_id)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
- [x] Ensure a consistent design & UX aesthetic --- v0.1.0
|
- [x] Ensure a consistent design & UX aesthetic --- v0.1.0
|
||||||
- [ ] Sensible CSS class names for a modular styling approach --- v0.2.0
|
- [ ] Sensible CSS class names for a modular styling approach --- v0.2.0
|
||||||
|
|
||||||
- [ ] Convert db_functions.php queries/statements into prepared SQL for protection against SQL injection --- v0.2.0
|
- [x] Convert db_functions.php queries/statements into prepared SQL for protection against SQL injection --- v0.2.0
|
||||||
|
|
||||||
- [ ] Email Handler:
|
- [ ] Email Handler:
|
||||||
- [ ] Email users subscribed to author or tag whenever a new article is posted. --- v0.3.0
|
- [ ] Email users subscribed to author or tag whenever a new article is posted. --- v0.3.0
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
#### Systems Interfaces
|
#### Systems Interfaces
|
||||||
- [x] Admin panel (manage articles & accounts) --- v0.2.0
|
- [x] Admin panel (manage articles & accounts) --- v0.2.0
|
||||||
|
|
||||||
- [ ] Implement a notification modal system for handling error and success messages. --- v0.2.0
|
- [ ] Implement a notification modal system for handling error and success messages. --- v0.3.0
|
||||||
|
|
||||||
- [ ] Accounts:
|
- [ ] Accounts:
|
||||||
#### Account CRUD --- account_functions.php
|
#### Account CRUD --- account_functions.php
|
||||||
@@ -61,11 +61,11 @@
|
|||||||
- [x] Delete Articles by Author (for account deletion) --- v0.1.0
|
- [x] Delete Articles by Author (for account deletion) --- v0.1.0
|
||||||
- [ ] Draft/unpublished status --- v0.2.0
|
- [ ] Draft/unpublished status --- v0.2.0
|
||||||
- [ ] Update Article by ID (required to be the author updating) --- v0.2.0
|
- [ ] Update Article by ID (required to be the author updating) --- v0.2.0
|
||||||
- [ ] Get Articles by Author --- v0.2.0
|
- [x] Get Articles by Author --- v0.2.0
|
||||||
- [ ] Sort / filter system --- v0.2.0
|
- [x] Sort / filter system --- v0.2.0
|
||||||
|
|
||||||
#### Article System Interface
|
#### Article System Interface
|
||||||
- [ ] Convert articles.php layout to a grid, to display a left hand column with a search/filtering system or table of contents. --- v0.2.0
|
- [x] Convert articles.php layout to a grid, to display a left hand column with a search/filtering system or table of contents. --- v0.2.0
|
||||||
- [ ] Advanced markdown editor or upload markdown, with media upload support (images & code files, requires contributor or higher auth) --- v0.3.0
|
- [ ] Advanced markdown editor or upload markdown, with media upload support (images & code files, requires contributor or higher auth) --- v0.3.0
|
||||||
|
|
||||||
### Unplanned but implemented
|
### Unplanned but implemented
|
||||||
|
|||||||
Reference in New Issue
Block a user