mirror of
https://codeberg.org/vlw/vlw.se.git
synced 2025-09-13 21:13:40 +02:00
wip: 2024-11-24T10:07:17+0100 (1732439237)
This commit is contained in:
parent
8bcf240843
commit
091aa46481
15 changed files with 236 additions and 186 deletions
|
@ -39,10 +39,7 @@
|
|||
->min(1)
|
||||
->max(parent::MYSQL_TEXT_MAX_LENGTH),
|
||||
|
||||
(new Rules(WorkModel::IS_LISTABLE->value))
|
||||
->type(Type::BOOLEAN),
|
||||
|
||||
(new Rules(WorkModel::IS_READABLE->value))
|
||||
(new Rules(WorkModel::IS_LISTED->value))
|
||||
->type(Type::BOOLEAN),
|
||||
|
||||
(new Rules(WorkModel::DATE_MODIFIED->value))
|
||||
|
|
|
@ -37,11 +37,7 @@
|
|||
->type(Type::STRING)
|
||||
->max(parent::MYSQL_TEXT_MAX_LENGTH),
|
||||
|
||||
(new Rules(WorkModel::IS_LISTABLE->value))
|
||||
->type(Type::BOOLEAN)
|
||||
->default(true),
|
||||
|
||||
(new Rules(WorkModel::IS_READABLE->value))
|
||||
(new Rules(WorkModel::IS_LISTED->value))
|
||||
->type(Type::BOOLEAN)
|
||||
->default(true),
|
||||
|
||||
|
@ -93,10 +89,10 @@
|
|||
->limit($_GET[PARAM_LIMIT])
|
||||
->select([
|
||||
WorkModel::ID->value,
|
||||
WorkModel::REF_NAMESPACE_ID->value,
|
||||
WorkModel::TITLE->value,
|
||||
WorkModel::SUMMARY->value,
|
||||
WorkModel::IS_LISTABLE->value,
|
||||
WorkModel::IS_READABLE->value,
|
||||
WorkModel::IS_LISTED->value,
|
||||
WorkModel::DATE_YEAR->value,
|
||||
WorkModel::DATE_MONTH->value,
|
||||
WorkModel::DATE_DAY->value,
|
||||
|
|
|
@ -47,10 +47,7 @@
|
|||
->min(1)
|
||||
->max(parent::MYSQL_TEXT_MAX_LENGTH),
|
||||
|
||||
(new Rules(WorkModel::IS_LISTABLE->value))
|
||||
->type(Type::BOOLEAN),
|
||||
|
||||
(new Rules(WorkModel::IS_READABLE->value))
|
||||
(new Rules(WorkModel::IS_LISTED->value))
|
||||
->type(Type::BOOLEAN),
|
||||
|
||||
(new Rules(WorkModel::DATE_MODIFIED->value))
|
||||
|
|
|
@ -41,11 +41,7 @@
|
|||
->max(parent::MYSQL_TEXT_MAX_LENGTH)
|
||||
->default(null),
|
||||
|
||||
(new Rules(WorkModel::IS_LISTABLE->value))
|
||||
->type(Type::BOOLEAN)
|
||||
->default(false),
|
||||
|
||||
(new Rules(WorkModel::IS_READABLE->value))
|
||||
(new Rules(WorkModel::IS_LISTED->value))
|
||||
->type(Type::BOOLEAN)
|
||||
->default(false),
|
||||
|
||||
|
|
|
@ -38,12 +38,11 @@
|
|||
WorkActionsModel::REF_WORK_ID->value,
|
||||
WorkActionsModel::DISPLAY_TEXT->value,
|
||||
WorkActionsModel::HREF->value,
|
||||
WorkActionsModel::CLASS_LIST->value,
|
||||
WorkActionsModel::EXTERNAL->value
|
||||
WorkActionsModel::CLASS_LIST->value
|
||||
]);
|
||||
|
||||
return $response->num_rows > 0
|
||||
? new Response($response->fetch_all(MYSQLI_ASSOC))
|
||||
? new Response(parent::index_array_by_key($response->fetch_all(MYSQLI_ASSOC), WorkActionsModel::REF_WORK_ID->value))
|
||||
: new Response([], 404);
|
||||
}
|
||||
}
|
|
@ -50,11 +50,7 @@
|
|||
(new Rules(WorkActionsModel::CLASS_LIST->value))
|
||||
->type(Type::ARRAY)
|
||||
->min(1)
|
||||
->default([]),
|
||||
|
||||
(new Rules(WorkActionsModel::EXTERNAL->value))
|
||||
->type(Type::BOOLEAN)
|
||||
->default(false)
|
||||
->default([])
|
||||
]);
|
||||
|
||||
parent::__construct(Databases::VLW, $this->ruleset);
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
]);
|
||||
|
||||
return $response->num_rows > 0
|
||||
? new Response($response->fetch_all(MYSQLI_ASSOC))
|
||||
? new Response(parent::index_array_by_key($response->fetch_all(MYSQLI_ASSOC), WorkTagsModel::REF_WORK_ID->value))
|
||||
: new Response([], 404);
|
||||
}
|
||||
}
|
|
@ -37,6 +37,11 @@
|
|||
);
|
||||
}
|
||||
|
||||
// Bail out if provided ReflectRules\Ruleset is invalid
|
||||
private static function eval_ruleset_or_exit(Ruleset $ruleset): ?Response {
|
||||
return !$ruleset->is_valid() ? new Response($ruleset->get_errors(), 422) : null;
|
||||
}
|
||||
|
||||
// Generate and return UUID4 string
|
||||
public static function gen_uuid4(): string {
|
||||
return sprintf("%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
|
||||
|
@ -76,8 +81,21 @@
|
|||
return $filters;
|
||||
}
|
||||
|
||||
// Bail out if provided ReflectRules\Ruleset is invalid
|
||||
private static function eval_ruleset_or_exit(Ruleset $ruleset): ?Response {
|
||||
return !$ruleset->is_valid() ? new Response($ruleset->get_errors(), 422) : null;
|
||||
public function index_array_by_key(array $input, string $key): array {
|
||||
$output = [];
|
||||
|
||||
foreach ($input as $item) {
|
||||
$idx = $item[$key];
|
||||
|
||||
// Create entry for key in output array if first item
|
||||
if (!array_key_exists($idx, $output)) {
|
||||
$output[$idx] = [];
|
||||
}
|
||||
|
||||
// Append item to array of array by key
|
||||
$output[$idx][] = $item;
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
|
@ -9,15 +9,15 @@
|
|||
|
||||
const TABLE = "work";
|
||||
|
||||
case ID = "id";
|
||||
case TITLE = "title";
|
||||
case SUMMARY = "summary";
|
||||
case COVER_SRCSET = "cover_srcset";
|
||||
case IS_LISTABLE = "is_listable";
|
||||
case IS_READABLE = "is_readable";
|
||||
case DATE_YEAR = "date_year";
|
||||
case DATE_MONTH = "date_month";
|
||||
case DATE_DAY = "date_day";
|
||||
case DATE_MODIFIED = "date_modified";
|
||||
case DATE_CREATED = "date_created";
|
||||
case ID = "id";
|
||||
case REF_NAMESPACE_ID = "ref_namespace_id";
|
||||
case TITLE = "title";
|
||||
case SUMMARY = "summary";
|
||||
case COVER_SRCSET = "cover_srcset";
|
||||
case IS_LISTED = "is_listed";
|
||||
case DATE_YEAR = "date_year";
|
||||
case DATE_MONTH = "date_month";
|
||||
case DATE_DAY = "date_day";
|
||||
case DATE_MODIFIED = "date_modified";
|
||||
case DATE_CREATED = "date_created";
|
||||
}
|
|
@ -6,8 +6,10 @@
|
|||
const TABLE = "work_actions";
|
||||
|
||||
case REF_WORK_ID = "ref_work_id";
|
||||
case ICON_PREFIX = "icon_prefix";
|
||||
case ICON_SUFFIX = "icon_suffix";
|
||||
case ORDER_IDX = "order_idx";
|
||||
case DISPLAY_TEXT = "display_text";
|
||||
case HREF = "href";
|
||||
case CLASS_LIST = "class_list";
|
||||
case EXTERNAL = "external";
|
||||
}
|
15
api/src/databases/models/Work/WorkNamespaces.php
Normal file
15
api/src/databases/models/Work/WorkNamespaces.php
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
namespace VLW\API\Databases\VLWdb\Models\Work;
|
||||
|
||||
enum WorkNamespacesModel: string {
|
||||
const TABLE = "work_actions";
|
||||
|
||||
case REF_WORK_ID = "ref_work_id";
|
||||
case ICON_PREFIX = "icon_prefix";
|
||||
case ICON_SUFFIX = "icon_suffix";
|
||||
case ORDER_IDX = "order_idx";
|
||||
case DISPLAY_TEXT = "display_text";
|
||||
case HREF = "href";
|
||||
case CLASS_LIST = "class_list";
|
||||
}
|
|
@ -10,6 +10,7 @@
|
|||
case VLW;
|
||||
case RELEASE;
|
||||
case WEBSITE;
|
||||
case REPO;
|
||||
}
|
||||
|
||||
enum WorkTagsModel: string {
|
||||
|
|
|
@ -66,11 +66,7 @@
|
|||
<?php foreach ($actions->json() as $action): ?>
|
||||
|
||||
<?php // Bind VV Interactions if link is same origin, else open in new tab ?>
|
||||
<?php if (!$action[WorkActionsModel::EXTERNAL->value]): ?>
|
||||
<a href="<?= $action[WorkActionsModel::HREF->value] ?>"><button class="inline <?= $action[WorkActionsModel::CLASS_LIST->value] ?>"><?= $action[WorkActionsModel::DISPLAY_TEXT->value] ?></button></a>
|
||||
<?php else: ?>
|
||||
<a href="<?= $action[WorkActionsModel::HREF->value] ?>" target="_blank"><button class="inline <?= $action[WorkActionsModel::CLASS_LIST->value] ?>"><?= $action[WorkActionsModel::DISPLAY_TEXT->value] ?></button></a>
|
||||
<?php endif; ?>
|
||||
<a href="<?= $action[WorkActionsModel::HREF->value] ?>" target="_blank"><button class="inline <?= $action[WorkActionsModel::CLASS_LIST->value] ?>"><?= $action[WorkActionsModel::DISPLAY_TEXT->value] ?></button></a>
|
||||
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
|
|
@ -1,8 +1,44 @@
|
|||
<?php
|
||||
|
||||
use Reflect\Response;
|
||||
|
||||
use VLW\Client\API;
|
||||
use VLW\API\Endpoints;
|
||||
|
||||
use VLW\API\Databases\VLWdb\Models\Work\WorkModel;
|
||||
|
||||
require_once VV::root("src/client/API.php");
|
||||
require_once VV::root("api/src/Endpoints.php");
|
||||
|
||||
require_once VV::root("api/src/databases/models/Work/Work.php");
|
||||
|
||||
// Number of items from the timeline to display on this page
|
||||
const TIMELINE_PREVIEW_LIMIT = 10;
|
||||
|
||||
$work = new class extends API {
|
||||
const ERROR_MSG = "Something went wrong";
|
||||
|
||||
private readonly Response $resp;
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
|
||||
// Get work items from endpoint
|
||||
$this->resp = $this->call(Endpoints::WORK->value)->params([
|
||||
WorkModel::IS_LISTED->value => true
|
||||
])->get();
|
||||
}
|
||||
|
||||
private function get_item(string $key): array {
|
||||
$idx = array_search($key, array_column($this->resp->json(), WorkModel::ID->value));
|
||||
return $this->resp->json()[$idx];
|
||||
}
|
||||
|
||||
public function get_summary(string $key): string {
|
||||
return $this->resp->ok ? $this->get_item($key)[WorkModel::SUMMARY->value] : self::ERROR_MSG;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
<style><?= VV::css("public/assets/css/pages/work") ?></style>
|
||||
<section class="git">
|
||||
|
@ -20,7 +56,7 @@
|
|||
<?= VV::embed("public/assets/media/icons/vegvisir.svg") ?>
|
||||
<h1>vegvisir</h1>
|
||||
</div>
|
||||
<p>Web navigation framework for PHP websites that does on the fly MPA-to-SPA routing between pages on the [open] web seas.</p>
|
||||
<p><?= $work->get_summary("vlw/vegvisir") ?></p>
|
||||
<div class="actions">
|
||||
<a href="https://vegvisir.vlw.se"><button class="inline">Read more</button></a>
|
||||
</div>
|
||||
|
@ -32,7 +68,7 @@
|
|||
<?= VV::embed("public/assets/media/icons/reflect.svg") ?>
|
||||
<h1>reflect</h1>
|
||||
</div>
|
||||
<p>A weird framework for building REST APIs in PHP with focus on native internal request routing and proxying.</p>
|
||||
<p><?= $work->get_summary("vlw/reflect") ?></p>
|
||||
<div class="actions">
|
||||
<a href="https://reflect.vlw.se"><button class="inline">Read more</button></a>
|
||||
</div>
|
||||
|
@ -43,7 +79,6 @@
|
|||
<featured-item>
|
||||
<div class="title">
|
||||
<?= VV::embed("public/assets/media/icons/vw.svg") ?>
|
||||
<button>website</button>
|
||||
</div>
|
||||
<h3>vlw.se</h3>
|
||||
<p>Can I put my own website here, is that cheating? Maybe, but I think this site counts as the most important thing I've personally created. I've only used my own libraries and frameworks to create this website, so it kind of works as a live demonstration of many of my web projects bundled together.</p>
|
||||
|
@ -69,7 +104,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<h3>vlw/php-mysql</h3>
|
||||
<p>Yet another abstraction library for the php-mysql extension. For this library, I was willing to sacrifice most of MySQL's flexibility that comes with string interpolation in favor of method chaining that adheres to an SQL-like syntax. For simple DML operations I think it's pretty intuitive.</p>
|
||||
<p><?= $work->get_summary("vlw/php-mysql") ?></p>
|
||||
<div class="actions">
|
||||
<a href="PHP"><button class="inline">read more</button></a>
|
||||
</div>
|
||||
|
@ -77,10 +112,9 @@
|
|||
<featured-item>
|
||||
<div class="title">
|
||||
<?= VV::embed("public/assets/media/icons/star.svg") ?>
|
||||
<button>website</button>
|
||||
</div>
|
||||
<h3>Website for iCellate Medical</h3>
|
||||
<p>Together with the iCellate team, I created a new front-end for the biopharma startup using my Vegvisir framework as the foundation.</p>
|
||||
<p><?= $work->get_summary("icellate/website") ?></p>
|
||||
<div class="actions">
|
||||
<a href=""><button class="inline">read more</button></a>
|
||||
</div>
|
||||
|
@ -88,10 +122,9 @@
|
|||
<featured-item>
|
||||
<div class="title">
|
||||
<?= VV::embed("public/assets/media/icons/star.svg") ?>
|
||||
<button>website</button>
|
||||
</div>
|
||||
<h3>Modernizing GeneMate by iCellate</h3>
|
||||
<p>Together with copy written by the amazing team at iCellate, and a new brand new appearance for the company, I helped design a new website and underlying systems for their GeneMate product.</p>
|
||||
<p><?= $work->get_summary("icellate/genemate") ?></p>
|
||||
<div class="actions">
|
||||
<a href=""><button class="inline">read more</button></a>
|
||||
</div>
|
||||
|
|
|
@ -19,154 +19,158 @@
|
|||
require_once VV::root("api/src/databases/models/Work/WorkTags.php");
|
||||
require_once VV::root("api/src/databases/models/Work/WorkActions.php");
|
||||
|
||||
// Connect to VLW API
|
||||
$api = new API();
|
||||
$work = new class extends API {
|
||||
private readonly Response $resp;
|
||||
private readonly Response $tags;
|
||||
private readonly Response $actions;
|
||||
|
||||
// Retreive rows from work endpoints
|
||||
$resp_work = $api->call(Endpoints::WORK->value)->params($_GET)->get();
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
|
||||
// Resolve tags and actions if we got work results
|
||||
if ($resp_work->ok) {
|
||||
$work_tags = $api->call(Endpoints::WORK_TAGS->value)->get()->json();
|
||||
$work_actions = $api->call(Endpoints::WORK_ACTIONS->value)->get()->json();
|
||||
}
|
||||
$this->resp = $this->call(Endpoints::WORK->value)->params([
|
||||
WorkModel::IS_LISTED->value => true
|
||||
])->get();
|
||||
|
||||
?>
|
||||
<style><?= VV::css("public/assets/css/pages/work/timeline") ?></style>
|
||||
|
||||
<?php if ($resp_work->ok): ?>
|
||||
<?php
|
||||
// Fetch metadata for work items if we got an ok from work endpoint
|
||||
if ($this->resp->ok) {
|
||||
$this->tags = $this->call(Endpoints::WORK_TAGS->value)->get();
|
||||
$this->actions = $this->call(Endpoints::WORK_ACTIONS->value)->get();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Order response from endpoint into a multi-dimensional array.
|
||||
For example, a single item created at 14th of February 2024 would be ordered like this
|
||||
[2024 => [[02 => [14 => [<row_data>]]]]]
|
||||
*/
|
||||
|
||||
$rows = [];
|
||||
// Create array of arrays ordered by decending year, month, day, items
|
||||
foreach ($resp_work->json() as $row) {
|
||||
// Create array for current year if it doesn't exist
|
||||
if (!array_key_exists($row[WorkModel::DATE_YEAR->value], $rows)) {
|
||||
$rows[$row[WorkModel::DATE_YEAR->value]] = [];
|
||||
public function get_timeline(): array {
|
||||
if (!$this->resp->ok) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Create array for current month if it doesn't exist
|
||||
if (!array_key_exists($row[WorkModel::DATE_MONTH->value], $rows[$row[WorkModel::DATE_YEAR->value]])) {
|
||||
$rows[$row[WorkModel::DATE_YEAR->value]][$row[WorkModel::DATE_MONTH->value]] = [];
|
||||
$timeline = [];
|
||||
|
||||
// Create array of arrays ordered by decending year, month, day, items
|
||||
foreach ($this->resp->json() as $row) {
|
||||
// Create array for current year if it doesn't exist
|
||||
if (!array_key_exists($row[WorkModel::DATE_YEAR->value], $timeline)) {
|
||||
$timeline[$row[WorkModel::DATE_YEAR->value]] = [];
|
||||
}
|
||||
|
||||
// Create array for current month if it doesn't exist
|
||||
if (!array_key_exists($row[WorkModel::DATE_MONTH->value], $timeline[$row[WorkModel::DATE_YEAR->value]])) {
|
||||
$timeline[$row[WorkModel::DATE_YEAR->value]][$row[WorkModel::DATE_MONTH->value]] = [];
|
||||
}
|
||||
|
||||
// Create array for current day if it doesn't exist
|
||||
if (!array_key_exists($row[WorkModel::DATE_DAY->value], $timeline[$row[WorkModel::DATE_YEAR->value]][$row[WorkModel::DATE_MONTH->value]])) {
|
||||
$timeline[$row[WorkModel::DATE_YEAR->value]][$row[WorkModel::DATE_MONTH->value]][$row[WorkModel::DATE_DAY->value]] = [];
|
||||
}
|
||||
|
||||
// Append item to ordered array
|
||||
$timeline[$row[WorkModel::DATE_YEAR->value]][$row[WorkModel::DATE_MONTH->value]][$row[WorkModel::DATE_DAY->value]][] = $row;
|
||||
}
|
||||
|
||||
// Create array for current day if it doesn't exist
|
||||
if (!array_key_exists($row[WorkModel::DATE_DAY->value], $rows[$row[WorkModel::DATE_YEAR->value]][$row[WorkModel::DATE_MONTH->value]])) {
|
||||
$rows[$row[WorkModel::DATE_YEAR->value]][$row[WorkModel::DATE_MONTH->value]][$row[WorkModel::DATE_DAY->value]] = [];
|
||||
}
|
||||
|
||||
// Append item to ordered array
|
||||
$rows[$row[WorkModel::DATE_YEAR->value]][$row[WorkModel::DATE_MONTH->value]][$row[WorkModel::DATE_DAY->value]][] = $row;
|
||||
return $timeline;
|
||||
}
|
||||
|
||||
?>
|
||||
public function get_tags(string $key): array {
|
||||
if (!$this->resp->ok) {
|
||||
return [];
|
||||
}
|
||||
|
||||
<section class="timeline">
|
||||
<?php // Get year int from key and array of months for current year ?>
|
||||
<?php foreach($rows as $year => $months): ?>
|
||||
<div class="year">
|
||||
<div class="track">
|
||||
<p><?= $year ?></p>
|
||||
</div>
|
||||
return in_array($key, $this->tags->json()) ? $this->tags->json()[$key] : [];
|
||||
}
|
||||
|
||||
<div class="months">
|
||||
<?php // Get month int from key and array of days for current month ?>
|
||||
<?php foreach($months as $month => $days): ?>
|
||||
<div class="month">
|
||||
<div class="track">
|
||||
<?php // Append leading zero to month ?>
|
||||
<p><?= sprintf("%02d", $month) ?></p>
|
||||
</div>
|
||||
public function get_actions(string $key): array {
|
||||
if (!$this->resp->ok) {
|
||||
return [];
|
||||
}
|
||||
|
||||
<div class="days">
|
||||
<?php // Get day int from key and array of items for current day ?>
|
||||
<?php foreach($days as $day => $items): ?>
|
||||
<div class="day">
|
||||
<div class="track">
|
||||
<?php // Append leading zero to day ?>
|
||||
<p><?= sprintf("%02d", $day) ?></p>
|
||||
</div>
|
||||
return in_array($key, $this->actions->json()) ? $this->actions->json()[$key] : [];
|
||||
}
|
||||
}
|
||||
|
||||
<div class="items">
|
||||
<?php foreach($items as $item): ?>
|
||||
<div class="item">
|
||||
|
||||
<?php // Get array index ids from tags array where work entity id matches ref_work_id ?>
|
||||
<?php $tag_ids = array_keys(array_column($work_tags, WorkTagsModel::REF_WORK_ID->value), $item[WorkModel::ID->value]); ?>
|
||||
|
||||
<?php // List tags if available ?>
|
||||
<?php if($tag_ids): ?>
|
||||
<div class="tags">
|
||||
<?php foreach($tag_ids as $tag_id): ?>
|
||||
<?php // Get tag details from tag array by index id ?>
|
||||
<?php $tag = $work_tags[$tag_id]; ?>
|
||||
|
||||
<p class="tag <?= $tag[WorkTagsModel::NAME->value] ?>"><?= $tag[WorkTagsModel::NAME->value] ?></p>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php // Show large heading if defined ?>
|
||||
<?php if (!empty($item[WorkModel::TITLE->value])): ?>
|
||||
<h2><?= $item[WorkModel::TITLE->value] ?></h2>
|
||||
<?php endif; ?>
|
||||
|
||||
<p><?= $item[WorkModel::SUMMARY->value] ?></p>
|
||||
|
||||
<?php // Get array index ids from actions array where work entity id matches ref_work_id ?>
|
||||
<?php $action_ids = array_keys(array_column($work_actions, WorkTagsModel::REF_WORK_ID->value), $item[WorkModel::ID->value]); ?>
|
||||
|
||||
<?php // List actions if defined for item ?>
|
||||
<?php if($action_ids): ?>
|
||||
<div class="actions">
|
||||
<?php foreach($action_ids as $action_id): ?>
|
||||
<?php
|
||||
// Get tag details from tag array by index id
|
||||
$action = $work_actions[$action_id];
|
||||
|
||||
$link_attr = !$action[WorkActionsModel::EXTERNAL->value]
|
||||
// Bind VV Interactions for local links
|
||||
? "vv='work' vv-call='navigate'"
|
||||
// Open external links in a new tab
|
||||
: "target='_blank'";
|
||||
|
||||
$link_href = $action[WorkActionsModel::HREF->value] === null
|
||||
// Navigate to work details page if no href is defined
|
||||
? "/work/{$item[WorkModel::ID->value]}"
|
||||
// Href is defined so use it directly
|
||||
: $action[WorkActionsModel::HREF->value];
|
||||
?>
|
||||
|
||||
<a href="<?= $link_href ?>" <?= $link_attr ?>><button class="inline <?= $action["class_list"] ?>"><?= $action["display_text"] ?></button></a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
?>
|
||||
<style><?= VV::css("public/assets/css/pages/work/timeline") ?></style>
|
||||
<section class="timeline">
|
||||
|
||||
<?php // Get year int from key and array of months for current year ?>
|
||||
<?php foreach ($work->get_timeline() as $year => $months): ?>
|
||||
<div class="year">
|
||||
<div class="track">
|
||||
<p><?= $year ?></p>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</section>
|
||||
<section class="note">
|
||||
<p>This is not really the end of the list. I will add some of my notable older work at some point.</p>
|
||||
</section>
|
||||
<?php else: ?>
|
||||
<p>Something went wrong!</p>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="months">
|
||||
<?php // Get month int from key and array of days for current month ?>
|
||||
<?php foreach ($months as $month => $days): ?>
|
||||
<div class="month">
|
||||
<div class="track">
|
||||
<?php // Append leading zero to month ?>
|
||||
<p><?= sprintf("%02d", $month) ?></p>
|
||||
</div>
|
||||
|
||||
<div class="days">
|
||||
<?php // Get day int from key and array of items for current day ?>
|
||||
<?php foreach ($days as $day => $items): ?>
|
||||
<div class="day">
|
||||
<div class="track">
|
||||
<?php // Append leading zero to day ?>
|
||||
<p><?= sprintf("%02d", $day) ?></p>
|
||||
</div>
|
||||
|
||||
<div class="items">
|
||||
<?php foreach ($items as $item): ?>
|
||||
<div class="item">
|
||||
|
||||
<?php // List tags if available ?>
|
||||
<?php if ($work->get_tags($item[WorkModel::ID->value])): ?>
|
||||
<div class="tags">
|
||||
<?php foreach ($work->get_tags($item[WorkModel::ID->value]) as $tag): ?>
|
||||
<p class="tag <?= $tag[WorkTagsModel::NAME->value] ?>"><?= $tag[WorkTagsModel::NAME->value] ?></p>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php // Show large heading if defined ?>
|
||||
<?php if (!empty($item[WorkModel::TITLE->value])): ?>
|
||||
<h2><?= $item[WorkModel::TITLE->value] ?></h2>
|
||||
<?php endif; ?>
|
||||
|
||||
<p><?= $item[WorkModel::SUMMARY->value] ?></p>
|
||||
|
||||
<div class="actions">
|
||||
<?php if ($work->get_actions($item[WorkModel::ID->value])): ?>
|
||||
|
||||
<?php // Display each action button ?>
|
||||
<?php foreach ($work->get_actions($item[WorkModel::ID->value]) as $action): ?>
|
||||
<a href="<?= $action[WorkActionsModel::HREF->value] ?>"><button class="inline <?= $action[WorkActionsModel::CLASS_LIST->value] ?>"><?= $action[WorkActionsModel::DISPLAY_TEXT->value] ?></button></a>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<?php // Display a link to namespaced page on vlw.se if no action is defined ?>
|
||||
<?php else: ?>
|
||||
<a href="<?= $item[WorkModel::ID->value] ?>"><button class="inline">read more</button></a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
|
||||
</section>
|
||||
<section class="note">
|
||||
<p>This is not really the end of the list. I will add some of my notable older work at some point.</p>
|
||||
</section>
|
||||
<script><?= VV::js("assets/js/pages/work/timeline") ?></script>
|
Loading…
Add table
Reference in a new issue