refine index layout. prep for user-specified timezones.

This commit is contained in:
Greg Sarjeant 2025-05-31 10:56:08 -04:00
parent 1514afebbe
commit 22a7ae948f
5 changed files with 150 additions and 58 deletions

4
.gitignore vendored
View File

@ -1,2 +1,4 @@
.vscode
*.sqlite
*.txt
*.txt

View File

@ -3,12 +3,12 @@ require_once __DIR__ . '/../bootstrap.php';
function save_tick(string $tick): void {
// build the tick path and filename from the current time
$date = new DateTime();
$now = new DateTime('now', new DateTimeZone('UTC'));
$year = $date->format('Y');
$month = $date->format('m');
$day = $date->format('d');
$time = $date->format('H:i:s');
$year = $now->format('Y');
$month = $now->format('m');
$day = $now->format('d');
$time = $now->format('H:i:s');
// build the full path to the tick file
$dir = TICKS_DIR . "/$year/$month";
@ -39,10 +39,16 @@ function stream_ticks(int $limit, int $offset = 0): Generator {
file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES)
);
// split the path to the current file into the date components
$pathParts = explode('/', str_replace('\\', '/', $file));
$date = $pathParts[count($pathParts) - 3] . '-' .
$pathParts[count($pathParts) - 2] . '-' .
pathinfo($pathParts[count($pathParts) - 1], PATHINFO_FILENAME);
// assign the different components to the appropriate part of the date
$year = $pathParts[count($pathParts) - 3];
$month = $pathParts[count($pathParts) - 2];
$day = pathinfo($pathParts[count($pathParts) - 1], PATHINFO_FILENAME);
// $date = $pathParts[count($pathParts) - 3] . '-' .
// $pathParts[count($pathParts) - 2] . '-' .
// pathinfo($pathParts[count($pathParts) - 1], PATHINFO_FILENAME);
foreach ($lines as $line) {
// just keep skipping ticks until we get to the starting point
@ -57,8 +63,11 @@ function stream_ticks(int $limit, int $offset = 0): Generator {
$time = $tickParts[0];
$tick = $tickParts[1];
// Build the timestamp from the date and time
// Ticks are always stored in UTC
$timestampUTC = "$year-$month-$day $time";
yield [
'timestamp' => $date . ' ' . $time,
'timestamp' => $timestampUTC,
'tick' => $tick,
];

View File

@ -1,34 +1,103 @@
@charset "UTF-8";
body {
max-width: 940px;
margin: 0 auto;
padding: 1em;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
background-color: whitesmoke;
color: black;
}
body { font-family: sans-serif; margin: 2em; }
/*
The two common display options for responsive layouts are flex and grid.
flex (aka Flexbox) aligns items either horizontally or vertically.
grid can align items in two dimensions.
grid also allows more precise positioning of elements, so I'm using that.
*/
.container {
display: grid;
}
.flex-container {
/*
Responsive layout - adjusts from 1 to 2 columns based on screen width
min-width makes the mobile (stacked) view the default
600px covers most mobile devices in portrait mode
Once the width exceeds that (e.g. desktops), it will convert to horizontal alignment
*/
@media (min-width: 600px) {
.container {
grid-template-columns: 1fr 2fr;
grid-gap: 2em;
}
}
.profile-row {
display: flex;
width: 100%;
gap: 0.5em;
}
/* Responsive layout - makes a one column layout instead of a two-column layout */
@media (max-width: 800px) {
.flex-container {
.tick-form {
display: flex;
flex-direction: column;
}
width: 100%;
gap: 0.5em;
}
.profile {
flex-grow: 0;
flex-shrink: 0;
flex-basis: 200px;
order: 1;
.tick-form textarea {
width: 100%;
box-sizing: border-box;
resize: none;
padding: 0.5em;
font-family: inherit;
font-size: 1em;
}
.ticks {
order: 2;
.tick-form button {
align-self: flex-end;
}
.tick { margin-bottom: 1em; }
.mood-bar {
display: flex;
width: 100%;
justify-content: space-between;
align-items: center;
gap: 0.5em;
}
.ticktime { color: gray; font-size: 0.9em; }
.admin-bar {
display: flex;
width: 100%;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
padding-top: 1em;
gap: 0.5em;
}
.ticktext {color: black; font-size: 1.0em; }
.admin-right {
display: flex;
align-items: center;
gap: 0.5em;
}
.admin-bar a,
.admin-bar span {
white-space: nowrap;
}
.tick {
margin-bottom: 1em;
}
.tick-time {
color: gray; font-size: 0.8em;
}
.tick-text {
color: black;
font-size: 1.0em;
}
.pagination a { margin: 0 5px; text-decoration: none; }

View File

@ -28,47 +28,59 @@ $ticks = iterator_to_array(stream_ticks($limit, $offset));
<link rel="stylesheet" href="<?= htmlspecialchars($config->basePath) ?>css/tkr.css?v=<?= time() ?>">
</head>
<body>
<h2><?= $config->siteDescription ?></h2>
<div class="flex-container">
<div class="profile">
<div class="container">
<section id="sidebar">
<h2>Hi, I'm <?= $user->displayName ?></h2>
<p><?= $user->about ?></p>
<p>Website: <?= escape_and_linkify($user->website) ?></p>
<div class="profile-row">
<div class="mood-bar">
<span>Current mood: <?= $user->mood ?></span>
<?php if ($isLoggedIn): ?>
<form class="tickform" action="save_tick.php" method="post">
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
<label for="tick">What's ticking?</label>
<input name="tick" id="tick" type="text">
<button type="submit">Tick</button>
</form>
<a href="<?= $config->basePath ?>set_mood.php">Change</a>
<?php endif; ?>
<p>Hi, I'm <?= $user->displayName ?></p>
<p><?= $user->about ?></p>
<p>Website: <?= escape_and_linkify($user->website) ?></p>
<p>Current mood: <?= $user->mood ?></p>
</div>
</div>
<?php if ($isLoggedIn): ?>
<a href="<?= $config->basePath ?>set_mood.php">Set your mood</a></p>
<p><a href="<?= $config->basePath . '/admin.php' ?>">Admin</a></p>
<p><a href="<?= $config->basePath ?>logout.php">Logout</a> <?= htmlspecialchars($user->username) ?> </p>
<hr/>
<div class="profile-row">
<form class="tick-form" action="save_tick.php" method="post">
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
<textarea name="tick" placeholder="What's ticking?" rows="3"></textarea>
<button type="submit">Tick</button>
</form>
</div>
<?php endif; ?>
<?php if ($isLoggedIn): ?>
<div class="admin-bar">
<a href="<?= $config->basePath . '/admin.php' ?>">Admin</a>
<div class="admin-right">
<a href="<?= $config->basePath ?>logout.php">Logout</a>
<span><?= htmlspecialchars($user->username) ?></span>
</div>
</div>
<?php else: ?>
<p><a href="<?= $config->basePath ?>login.php">Login</a></p>
<p><a href="<?= $config->basePath ?>login.php">Login</a></p>
<?php endif; ?>
</div>
<div class="ticks">
</section>
<section id="ticks">
<h2><?= $config->siteDescription ?></h2>
<?php foreach ($ticks as $tick): ?>
<div class="tick">
<span class="ticktime"><?= htmlspecialchars($tick['timestamp']) ?></span>
<span class="ticktext"><?= escape_and_linkify($tick['tick']) ?></span>
</div>
<article class="tick">
<div class="tick-time"><?= htmlspecialchars($tick['timestamp']) ?></div>
<span class="tick-text"><?= escape_and_linkify($tick['tick']) ?></span>
</article>
<?php endforeach; ?>
</div>
<div class="pagination">
<div class="pagination">
<?php if ($page > 1): ?>
<a href="?page=<?= $page - 1 ?>">&laquo; Newer</a>
<a href="?page=<?= $page - 1 ?>">&laquo; Newer</a>
<?php endif; ?>
<?php if (count($ticks) === $limit): ?>
<a href="?page=<?= $page + 1 ?>">Older &raquo;</a>
<a href="?page=<?= $page + 1 ?>">Older &raquo;</a>
<?php endif; ?>
</div>
</section>
</div>
</body>
</body>
</html>

View File

@ -33,8 +33,8 @@ echo '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
?>
<item>
<title><?php echo htmlspecialchars(date(DATE_RFC7231, strtotime($tick['timestamp']))); ?></title>
<link><?php echo htmlspecialchars("$basePath/tick.php?path=$tickPath"); ?></link>
<title><?php echo htmlspecialchars($tick['tick']); ?></title>
<link><?php echo htmlspecialchars("$config->basePath/tick.php?path=$tickPath"); ?></link>
<description><?php echo htmlspecialchars($tick['tick']); ?></description>
<pubDate><?php echo date(DATE_RSS, strtotime($tick['timestamp'])); ?></pubDate>
<guid><?php echo htmlspecialchars($tickPath); ?></guid>