From 2074a096636acd04f5149388a93c3370e08b7061 Mon Sep 17 00:00:00 2001 From: Sky Johnson Date: Thu, 19 Dec 2024 23:16:59 -0600 Subject: [PATCH] Build out new table generator --- public/css/admin.css | 34 ++++++++++++++++++- src/actions/admin.php | 75 ++++++++++++++++++++++++----------------- src/actions/install.php | 46 ++++++++++++------------- src/actions/users.php | 3 +- src/bootstrap.php | 13 +++++-- 5 files changed, 112 insertions(+), 59 deletions(-) diff --git a/public/css/admin.css b/public/css/admin.css index c871959..17c7229 100644 --- a/public/css/admin.css +++ b/public/css/admin.css @@ -1,5 +1,6 @@ :root { --font-size: 16px; + --font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; } * { @@ -10,7 +11,7 @@ html { font-size: var(--font-size); - font-family: sans-serif; + font-family: var(--font-family); } body { @@ -49,6 +50,37 @@ main > section { table { width: 100%; + border-collapse: collapse; + outline-width: none; + font-family: var(--font-family); + border: 1px solid rgba(0, 0, 0, 0.1); + + & > caption { + margin: 1rem; + } + + & :is(td,th) { + border: 1px solid rgba(0, 0, 0, 0.4); + padding: 0.5rem 1rem; + } + + & thead tr { + background: rgba(0, 0, 0, 0.1); + } + + & tbody tr:nth-of-type(even) { + background: rgba(0, 0, 0, 0.1); + &:hover { background: rgba(0, 0, 0, 0.2); } + } + + td:hover { + color: white; + background: rgba(0, 0, 0, 0.1); + } + + tr:hover { + background: rgba(0, 0, 0, 0.2); + } } a { diff --git a/src/actions/admin.php b/src/actions/admin.php index 776fc24..bb8bdad 100644 --- a/src/actions/admin.php +++ b/src/actions/admin.php @@ -5,10 +5,11 @@ namespace Admin; use Router; +use SQLite3Result; function register_routes(Router $r): Router { - if (user()->authlevel === 1) { + if (user() !== false && user()->authlevel === 1) { $r->get('/admin', 'Admin\donothing'); $r->form('/admin/main', 'Admin\primary'); @@ -111,21 +112,9 @@ function primary(): string */ function items(): string { - $items = db()->query('SELECT id, name FROM items ORDER BY id;'); - $page = "

Edit Items

Click an item's name to edit it.

\n"; - - $hasItems = false; - while ($row = $items->fetchArray(SQLITE3_BOTH)) { - $hasItems = true; - $page .= << - - - - HTML; - } - - if (!$hasItems) $page .= "\n"; + $items = db()->query('SELECT * FROM items ORDER BY id;'); + $page = "

Edit Items

Click an item's name or ID to edit it.

{$row["id"]}{$row["name"]}
No items found.
\n"; + $page .= build_bulk_table($items, 'name', '/admin/items'); page_title('Admin: Items'); return \Render\content($page . '
', 'layouts/admin'); @@ -174,21 +163,9 @@ function edit_item(int $id): string */ function drops() { + $drops = db()->query('SELECT * FROM drops ORDER BY id;'); $page = "

Edit Drops

Click an item's name to edit it.

\n"; - - $drops = db()->query('SELECT id, name FROM drops ORDER BY id;'); - $has_drops = false; - while ($row = $drops->fetchArray(SQLITE3_ASSOC)) { - $has_drops = true; - $page .= << - - - - HTML; - } - - if (!$has_drops) { $page .= "\n"; } + $page .= build_bulk_table($drops, 'name', '/admin/drops'); page_title('Admin: Drops'); return \Render\content($page . '
{$row["id"]}{$row["name"]}
No drops found.
', 'layouts/admin'); @@ -870,3 +847,41 @@ function addnews() display_admin($page, "Add News"); } + +/** + * Build an HTML table containing all columns and rows of a given data structure. Takes a SQLiteResult3 of a SELECT * + * query. + */ +function build_bulk_table(SQLite3Result $query_data, string $edit_column, string $edit_link): string +{ + $data = []; + while ($row = $query_data->fetchArray(SQLITE3_ASSOC)) $data[] = $row; + if (empty($data)) return 'No data.'; + + $columns = array_diff(array_keys($data[0]), ['password']); // Filter columns inline + $html = ''; + foreach ($columns as $_) $html .= ''; + $html .= ''; + foreach ($columns as $column) { + if ($column === 'id') $column = 'ID'; + $html .= ''; + } + $html .= ''; + + foreach ($data as $row) { + $html .= ''; + foreach ($columns as $column) { + $name = make_safe($row[$column]); + if (in_array($column, ['id', $edit_column])) { + $html .= <<{$name} + HTML; + } else { + $html .= ""; + } + } + $html .= ''; + } + + return $html . '
' . make_safe(ucfirst($column)) . '
$name
'; +} diff --git a/src/actions/install.php b/src/actions/install.php index fc64d21..194d267 100644 --- a/src/actions/install.php +++ b/src/actions/install.php @@ -21,7 +21,7 @@ function register_routes(Router $r): Router */ function first() { - echo << Dragon Knight Installation @@ -43,7 +43,7 @@ function second() { if (file_exists('../database.db')) unlink('../database.db'); - echo "Dragon Knight InstallationDragon Knight Installation: Page Two

"; + $page = "Dragon Knight InstallationDragon Knight Installation: Page Two

"; $query = db()->exec(<<exec(<<exec(<<exec(<<exec(<<exec(<<exec(<<exec(<<exec(<<exec(<<exec(<<exec("INSERT INTO news (content) VALUES ('This is the first news post. Please use the admin control panel to add another one and make this one go away.');"); - echo table_status_msg($query === true, 'News', 'populate'); + $page .= table_status_msg($query === true, 'News', 'populate'); $query = db()->exec(<<exec(<<exec(<<exec(<<exec(<<Database setup complete in $time seconds.

Click here to continue with installation."; + return $page . "
Database setup complete in $time seconds.

Click here to continue with installation."; } /** @@ -629,7 +629,7 @@ function second() */ function third() { - echo << Dragon Knight Installation @@ -678,7 +678,7 @@ function fourth() file_put_contents('../.installed', date('Y-m-d H:i:s')); - echo << Dragon Knight Installation @@ -708,7 +708,7 @@ function fifth() exit('Dragon Knight was unable to send your URL. Please go back and try again, or just continue on to the game.'); } - echo << Dragon Knight Installation diff --git a/src/actions/users.php b/src/actions/users.php index ac73490..8f100fb 100644 --- a/src/actions/users.php +++ b/src/actions/users.php @@ -26,8 +26,7 @@ function login() if (is_post()) { $form = validate($_POST, [ 'username' => ['length:3-18', 'alpha-spaces'], - 'password' => ['length:6-255'], - 'remember' => ['bool'] + 'password' => ['length:6-255'] ]); if (!$form['valid']) exit(ul_from_validate_errors($form['errors'])); diff --git a/src/bootstrap.php b/src/bootstrap.php index 34304f1..b752958 100644 --- a/src/bootstrap.php +++ b/src/bootstrap.php @@ -23,11 +23,18 @@ $uri = explode('/', trim($_SERVER['REQUEST_URI'], '/')); $GLOBALS['cache'] = []; $GLOBALS['state'] = []; -if (!file_exists('../.installed') && $uri[0] !== 'install') { +/** + * These are table names whose data we want to be able to edit in the admin panel in bulk. + */ +define('ADMIN_BULK_DATA_STRUCTS', [ + 'users', 'items', 'drops', 'towns', 'monsters', 'levels', 'spells' +]); + +if (!file_exists('../.installed') && $uri[0] !== 'install') { // need to install the game redirect('/install'); -} elseif (file_exists(('../.installed')) && $uri[0] === 'install') { +} elseif (file_exists(('../.installed')) && $uri[0] === 'install') { // game is installed, go play! redirect('/'); -} elseif (file_exists(('../.installed')) && $uri[0] !== 'install') { +} elseif (file_exists(('../.installed')) && $uri[0] !== 'install') { // boostrap the game if (!env('game_open')) { echo Render\content('The game is currently closed for maintanence. Please check back later.'); exit;