This commit is contained in:
2026-06-13 15:59:29 -04:00
parent ef3fe990b8
commit d61a763d2a

View File

@@ -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')) {
if (!function_exists('cry01_load_config')) { \head_add_css('/addon/vs01/view/css/vs01-directory.css');
require_once 'addon/cry01/cry01_chain.php';
} }
$config = cry01_load_config(); $listings = $this->load_listings();
$path = $config['listings_file'] ?? ''; return \KdxDirectoryWidget::render($listings, 'cry01');
$listings = $this->load_listings($path);
return $this->render_directory($listings, $config);
} }
private function load_listings($path) { private function load_listings() {
// Loads listings.json from the operator-configured path. $config = $this->load_config();
if (!$path) return ['core' => [], 'tier1' => [], 'tier2' => [], 'other' => []]; $path = $config['listings_file'] ?? 'addon/cry01/listings.json';
$raw = @file_get_contents($path); $raw = @file_get_contents($path);
if ($raw === false) return ['core' => [], 'tier1' => [], 'tier2' => [], 'other' => []]; if ($raw === false) return ['core' => [], 'tier1' => [], 'tier2' => [], 'other' => []];
$data = json_decode($raw, true); $data = json_decode($raw, true);
return (json_last_error() === JSON_ERROR_NONE) return (json_last_error() === JSON_ERROR_NONE) ? $data : ['core' => [], 'tier1' => [], 'tier2' => [], 'other' => []];
? $data
: ['core' => [], 'tier1' => [], 'tier2' => [], 'other' => []];
} }
private function render_directory($listings, $config) { private function load_config() {
// Renders the four-tab Bootstrap directory widget. if (!function_exists('cry01_load_config')) {
$default_tab = $config['directory_default_tab'] ?? 'core'; require_once 'addon/cry01/cry01_chain.php';
$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>'; return cry01_load_config();
$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');
} }
} }