Updated
This commit is contained in:
@@ -2,132 +2,31 @@
|
|||||||
|
|
||||||
namespace Zotlabs\Widget;
|
namespace Zotlabs\Widget;
|
||||||
|
|
||||||
/**
|
require_once 'addon/vs01/directory_widget.php';
|
||||||
* Cry01 — sidebar widget.
|
|
||||||
* Renders the institutional directory for the cry01 addon.
|
|
||||||
* Follows the standard four-tab pattern: Core, Tier-I, Tier-II, Other.
|
|
||||||
*/
|
|
||||||
class Cry01 {
|
class Cry01 {
|
||||||
|
|
||||||
public function widget($arr) {
|
public function widget($arr) {
|
||||||
// Loads listings and renders the four-tab institutional directory.
|
if (function_exists('head_add_css')) {
|
||||||
|
\head_add_css('/addon/vs01/view/css/vs01-directory.css');
|
||||||
|
}
|
||||||
|
$listings = $this->load_listings();
|
||||||
|
return \KdxDirectoryWidget::render($listings, 'cry01');
|
||||||
|
}
|
||||||
|
|
||||||
|
private function load_listings() {
|
||||||
|
$config = $this->load_config();
|
||||||
|
$path = $config['listings_file'] ?? 'addon/cry01/listings.json';
|
||||||
|
$raw = @file_get_contents($path);
|
||||||
|
if ($raw === false) return ['core' => [], 'tier1' => [], 'tier2' => [], 'other' => []];
|
||||||
|
$data = json_decode($raw, true);
|
||||||
|
return (json_last_error() === JSON_ERROR_NONE) ? $data : ['core' => [], 'tier1' => [], 'tier2' => [], 'other' => []];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function load_config() {
|
||||||
if (!function_exists('cry01_load_config')) {
|
if (!function_exists('cry01_load_config')) {
|
||||||
require_once 'addon/cry01/cry01_chain.php';
|
require_once 'addon/cry01/cry01_chain.php';
|
||||||
}
|
}
|
||||||
$config = cry01_load_config();
|
return cry01_load_config();
|
||||||
$path = $config['listings_file'] ?? '';
|
|
||||||
$listings = $this->load_listings($path);
|
|
||||||
return $this->render_directory($listings, $config);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function load_listings($path) {
|
|
||||||
// Loads listings.json from the operator-configured path.
|
|
||||||
if (!$path) return ['core' => [], 'tier1' => [], 'tier2' => [], 'other' => []];
|
|
||||||
$raw = @file_get_contents($path);
|
|
||||||
if ($raw === false) return ['core' => [], 'tier1' => [], 'tier2' => [], 'other' => []];
|
|
||||||
$data = json_decode($raw, true);
|
|
||||||
return (json_last_error() === JSON_ERROR_NONE)
|
|
||||||
? $data
|
|
||||||
: ['core' => [], 'tier1' => [], 'tier2' => [], 'other' => []];
|
|
||||||
}
|
|
||||||
|
|
||||||
private function render_directory($listings, $config) {
|
|
||||||
// Renders the four-tab Bootstrap directory widget.
|
|
||||||
$default_tab = $config['directory_default_tab'] ?? 'core';
|
|
||||||
$uid = 'cry01-dir-' . substr(md5(uniqid()), 0, 6);
|
|
||||||
|
|
||||||
$tabs = [
|
|
||||||
'core' => 'Core',
|
|
||||||
'tier1' => 'Tier-I',
|
|
||||||
'tier2' => 'Tier-II',
|
|
||||||
'other' => 'Other',
|
|
||||||
];
|
|
||||||
|
|
||||||
$out = '<div class="cry01-directory">';
|
|
||||||
$out .= '<ul class="nav nav-tabs nav-tabs-sm mb-2" id="' . $uid . '-tabs" role="tablist">';
|
|
||||||
foreach ($tabs as $key => $label) {
|
|
||||||
$active = ($key === $default_tab) ? 'active' : '';
|
|
||||||
$out .= '<li class="nav-item" role="presentation">';
|
|
||||||
$out .= '<button class="nav-link ' . $active . '" id="' . $uid . '-' . $key . '-tab"
|
|
||||||
data-bs-toggle="tab"
|
|
||||||
data-bs-target="#' . $uid . '-' . $key . '"
|
|
||||||
type="button" role="tab">' . $this->h($label) . '</button>';
|
|
||||||
$out .= '</li>';
|
|
||||||
}
|
|
||||||
$out .= '</ul>';
|
|
||||||
|
|
||||||
$out .= '<div class="tab-content">';
|
|
||||||
foreach ($tabs as $key => $label) {
|
|
||||||
$active = ($key === $default_tab) ? 'show active' : '';
|
|
||||||
$out .= '<div class="tab-pane fade ' . $active . '" id="' . $uid . '-' . $key . '" role="tabpanel">';
|
|
||||||
$out .= ($key === 'core')
|
|
||||||
? $this->render_core_tab($listings['core'] ?? [])
|
|
||||||
: $this->render_tier_tab($listings[$key] ?? [], $label);
|
|
||||||
$out .= '</div>';
|
|
||||||
}
|
|
||||||
$out .= '</div></div>';
|
|
||||||
return $out;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function render_core_tab($core) {
|
|
||||||
// Renders the three permanent Core slots. Pending slots show invitation text.
|
|
||||||
$slots = [
|
|
||||||
'taxonomy-authority' => ['role' => 'Taxonomy Authority', 'desc' => 'The institutional source of the case law categories this diagnostic record is organized by.'],
|
|
||||||
'methodology-certifier' => ['role' => 'Methodology Certifier', 'desc' => 'The law firm whose professional association with this project certifies the diagnostic record meets a standard the legal community can use.'],
|
|
||||||
'peer-operator' => ['role' => 'Peer Operator', 'desc' => 'The cooperating Civic Infrastructure host who can independently verify, support, and if necessary continue this diagnostic record.'],
|
|
||||||
];
|
|
||||||
|
|
||||||
$indexed = [];
|
|
||||||
foreach ($core as $entry) {
|
|
||||||
$indexed[$entry['slot'] ?? ''] = $entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
$out = '';
|
|
||||||
foreach ($slots as $slot_id => $slot_def) {
|
|
||||||
$entry = $indexed[$slot_id] ?? [];
|
|
||||||
$status = $entry['status'] ?? 'pending';
|
|
||||||
$out .= '<div class="cry01-dir-slot mb-2">';
|
|
||||||
if ($status === 'pending' || empty($entry['name'])) {
|
|
||||||
$out .= '<div class="text-muted small fw-semibold">' . $this->h($slot_def['role']) . '</div>';
|
|
||||||
$out .= '<div class="text-muted small">' . $this->h($slot_def['desc']) . '</div>';
|
|
||||||
$out .= '<div class="text-muted small fst-italic">Invitation pending</div>';
|
|
||||||
} else {
|
|
||||||
$url = $entry['url'] ?? '';
|
|
||||||
$name = $this->h($entry['name']);
|
|
||||||
$out .= '<div class="small fw-semibold">';
|
|
||||||
$out .= $url ? '<a href="' . $this->h($url) . '" target="_blank" rel="noopener">' . $name . '</a>' : $name;
|
|
||||||
$out .= '</div>';
|
|
||||||
$out .= '<div class="text-muted small">' . $this->h($slot_def['role']) . '</div>';
|
|
||||||
}
|
|
||||||
$out .= '</div>';
|
|
||||||
}
|
|
||||||
return $out;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function render_tier_tab($entries, $label) {
|
|
||||||
// Renders a tier tab. Shows placeholder text if no entries.
|
|
||||||
if (empty($entries)) {
|
|
||||||
return '<p class="text-muted small fst-italic">No ' . $this->h($label) . ' listings yet.</p>';
|
|
||||||
}
|
|
||||||
$out = '';
|
|
||||||
foreach ($entries as $entry) {
|
|
||||||
$name = $this->h($entry['name'] ?? '');
|
|
||||||
$role = $this->h($entry['role'] ?? '');
|
|
||||||
$url = $entry['url'] ?? '';
|
|
||||||
$desc = $this->h($entry['description'] ?? '');
|
|
||||||
$out .= '<div class="cry01-dir-entry mb-2">';
|
|
||||||
$out .= '<div class="small fw-semibold">';
|
|
||||||
$out .= $url ? '<a href="' . $this->h($url) . '" target="_blank" rel="noopener">' . $name . '</a>' : $name;
|
|
||||||
$out .= '</div>';
|
|
||||||
if ($role) $out .= '<div class="text-muted small">' . $role . '</div>';
|
|
||||||
if ($desc) $out .= '<div class="text-muted small">' . $desc . '</div>';
|
|
||||||
$out .= '</div>';
|
|
||||||
}
|
|
||||||
return $out;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function h($value) {
|
|
||||||
// HTML-escapes a value for safe output.
|
|
||||||
return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user