Compare commits
2
Commits
a2b626b192
...
f34e9bad57
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f34e9bad57 | ||
|
|
b1640cdac4 |
@@ -80,6 +80,10 @@
|
|||||||
#default: hermes
|
#default: hermes
|
||||||
# MQTT_CLIENT_ID_PREFIX=hermes
|
# MQTT_CLIENT_ID_PREFIX=hermes
|
||||||
|
|
||||||
|
# MQTT keepalive interval (seconds). Used by paho-mqtt client connections.
|
||||||
|
#default: 60
|
||||||
|
# MQTT_KEEPALIVE=60
|
||||||
|
|
||||||
# Log level for MAM runtime components (DEBUG, INFO, WARN, ERROR).
|
# Log level for MAM runtime components (DEBUG, INFO, WARN, ERROR).
|
||||||
#default: INFO
|
#default: INFO
|
||||||
# MAM_LOG_LEVEL=INFO
|
# MAM_LOG_LEVEL=INFO
|
||||||
@@ -112,6 +116,32 @@
|
|||||||
#default: <cwd>/.mam/delegate_job_logs
|
#default: <cwd>/.mam/delegate_job_logs
|
||||||
# DELEGATE_JOB_LOGS_DIR=/path/to/workspace/.mam/delegate_job_logs
|
# DELEGATE_JOB_LOGS_DIR=/path/to/workspace/.mam/delegate_job_logs
|
||||||
|
|
||||||
|
# Max attempts to poll for pane renderer quiescence in send_keys_safe.
|
||||||
|
#default: 20
|
||||||
|
# SKS_QUIESCENT_TRIES=20
|
||||||
|
|
||||||
|
# Interval (seconds) between pane quiescence capture polls.
|
||||||
|
#default: 0.5
|
||||||
|
# SKS_QUIESCENT_INTERVAL=0.5
|
||||||
|
|
||||||
|
# Consecutive empty captures to conclude unobservable/headless mode early.
|
||||||
|
#default: 3
|
||||||
|
# SKS_EMPTY_GIVEUP=3
|
||||||
|
|
||||||
|
# Minimum columns a pane must retain after a vertical split (2xK layout engine).
|
||||||
|
#default: 60
|
||||||
|
# MAM_MIN_PANE_COLS=60
|
||||||
|
|
||||||
|
# Minimum rows a pane must retain after a horizontal split (2xK layout engine).
|
||||||
|
#default: 20
|
||||||
|
# MAM_MIN_PANE_ROWS=20
|
||||||
|
|
||||||
|
# Maximum number of columns a workspace may grow to before the engine reports
|
||||||
|
# 'overflow' (which makes lib.sh create a fresh workspace instead of splitting).
|
||||||
|
# Applies to both measured (GUI) and headless 0x0 layouts.
|
||||||
|
#default: (unset -> no column cap)
|
||||||
|
# MAM_MAX_PANE_COLS=3
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# deploy / distribution source (for forks/mirrors)
|
# deploy / distribution source (for forks/mirrors)
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
|||||||
@@ -68,7 +68,9 @@ Strong success criteria let you loop independently. Weak criteria ("make it work
|
|||||||
**These guidelines are working if:** fewer unnecessary changes in diffs, fewer rewrites due to overcomplication, and clarifying questions come before implementation rather than after mistakes.
|
**These guidelines are working if:** fewer unnecessary changes in diffs, fewer rewrites due to overcomplication, and clarifying questions come before implementation rather than after mistakes.
|
||||||
|
|
||||||
Read [MULTI_AGENT_RULES.md](.agents/MULTI_AGENT_RULES.md) (or [Korean version](.agents/MULTI_AGENT_RULES.ko.md)) and [multi-agent-mux-loop/SKILL.md](.agents/skills/multi-agent-mux-loop/SKILL.md) first before working and follow the instructions for orchestration and collaboration.
|
Read [MULTI_AGENT_RULES.md](.agents/MULTI_AGENT_RULES.md) (or [Korean version](.agents/MULTI_AGENT_RULES.ko.md)) and [multi-agent-mux-loop/SKILL.md](.agents/skills/multi-agent-mux-loop/SKILL.md) first before working and follow the instructions for orchestration and collaboration.
|
||||||
<!-- BEGIN MAM ORCHESTRATION -->
|
|
||||||
# 🤖 Multi-Agent Orchestration Guidelines
|
## 5. Orchestrator Scope Guard (O-3)
|
||||||
Please refer to [.agents/MULTI_AGENT_RULES.md](file://./.agents/MULTI_AGENT_RULES.md) for detailed collaborative rules and state flow constraints.
|
|
||||||
<!-- END MAM ORCHESTRATION -->
|
**Normal vs. Orchestration Modes**
|
||||||
|
- **Normal Mode**: The orchestrator acts as Main Creator and may edit files directly.
|
||||||
|
- **Loop Active Mode (`/multi-agent-mux-loop`)**: Direct file mutation is intercepted by `.agents/hooks.json`. Do not seek workarounds when a tool call is denied — delegate the task immediately via `run_loop.sh`.
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
:root {
|
:root {
|
||||||
color-scheme: light;
|
color-scheme: light;
|
||||||
|
|
||||||
/* Offline System & CSS Font Variables */
|
/* Offline System & CSS Font Variables */
|
||||||
--font-geist: 'Geist', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
--font-geist: 'Geist', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||||
--font-geist-mono: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
--font-geist-mono: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
||||||
--font-display: 'Fraunces', Georgia, Cambria, 'Times New Roman', Times, serif;
|
--font-display: 'Fraunces', Georgia, Cambria, 'Times New Roman', Times, serif;
|
||||||
|
|||||||
@@ -1,61 +1,59 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
import type { Metadata } from "next";
|
||||||
import { semesters } from "../../content/lectures";
|
import { semesters } from "../../content/lectures";
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: "Lectures",
|
||||||
|
description: "AI Agent Networking Lab (ANL) lecture courses and curriculum history",
|
||||||
|
};
|
||||||
|
|
||||||
export default function LecturesPage() {
|
export default function LecturesPage() {
|
||||||
const recentSemesters = semesters.slice(0, 3);
|
const recentSemesters = semesters.slice(0, 3);
|
||||||
const olderSemesters = semesters.slice(3);
|
const olderSemesters = semesters.slice(3);
|
||||||
|
|
||||||
|
const oldestSem = olderSemesters[olderSemesters.length - 1];
|
||||||
|
const newestOlderSem = olderSemesters[0];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container-content space-y-12 md:space-y-16 pt-10 md:pt-16 pb-16 md:pb-24">
|
<div className="container-content py-8 sm:py-12 space-y-10 sm:space-y-14">
|
||||||
{/* Header */}
|
{/* Page Header */}
|
||||||
<section className="space-y-3">
|
<section>
|
||||||
<div className="flex items-center gap-3">
|
<h1 className="font-serif text-4xl sm:text-5xl font-normal text-ink tracking-tight">
|
||||||
<span className="h-px w-8 bg-cobalt-dark"></span>
|
LECTURES
|
||||||
<span className="font-mono text-xs tracking-widest uppercase text-cobalt-dark font-bold">
|
|
||||||
Academic Courses
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<h1 className="font-serif text-4xl sm:text-5xl font-normal text-ink">
|
|
||||||
강의 이력
|
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-ink-mute text-base max-w-2xl">
|
|
||||||
2016년 가을학기부터 2026년 봄학기까지 개설된 네트워크 및 소프트웨어 분야 약 20개 학기의 학부/대학원 강의 목록입니다.
|
|
||||||
</p>
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Recent 3 Semesters */}
|
{/* Recent 3 Semesters */}
|
||||||
<section className="space-y-6 pt-6 md:pt-10 border-t border-line">
|
<section className="space-y-6 pt-6 md:pt-8 border-t border-line">
|
||||||
<div className="flex justify-between items-end">
|
<div className="flex justify-between items-center">
|
||||||
<div>
|
<h2 className="font-serif text-2xl sm:text-3xl font-normal text-cobalt-dark">
|
||||||
<div className="font-mono text-xs text-cobalt-dark uppercase tracking-widest font-bold">
|
Recent Courses
|
||||||
Recent Courses ({recentSemesters.length} Semesters)
|
</h2>
|
||||||
</div>
|
<span className="font-mono text-xs text-ink-mute hidden sm:inline">
|
||||||
<h2 className="font-serif text-3xl font-normal text-ink mt-1">
|
Latest 3 Semesters
|
||||||
최근 개설 강의
|
</span>
|
||||||
</h2>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-5 sm:gap-6">
|
||||||
{recentSemesters.map((sem, idx) => (
|
{recentSemesters.map((sem, idx) => (
|
||||||
<div
|
<div
|
||||||
key={idx}
|
key={idx}
|
||||||
className="bg-paper p-6 rounded-lg border border-line space-y-4 flex flex-col justify-between"
|
className="bg-paper p-5 sm:p-6 rounded-lg border border-line space-y-4 flex flex-col justify-between shadow-sm"
|
||||||
>
|
>
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<div className="flex justify-between items-center border-b border-line pb-2">
|
<div className="flex justify-between items-center border-b border-line pb-2.5">
|
||||||
<span className="font-serif text-xl font-normal text-ink">
|
<span className="font-serif text-lg sm:text-xl font-normal text-ink">
|
||||||
{sem.term} {sem.year}
|
{sem.term} {sem.year}
|
||||||
</span>
|
</span>
|
||||||
<span className="font-mono text-xs text-vermillion-dark font-bold">
|
<span className="font-mono text-[0.7rem] uppercase tracking-wider text-vermillion-dark font-bold px-2 py-0.5 rounded bg-vermillion-dark/10">
|
||||||
Latest
|
Latest
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul className="space-y-2 pt-1">
|
<ul className="space-y-2.5 pt-1">
|
||||||
{sem.courses.map((c, cIdx) => (
|
{sem.courses.map((c, cIdx) => (
|
||||||
<li key={cIdx} className="space-y-0.5">
|
<li key={cIdx} className="space-y-0.5">
|
||||||
<div className="font-serif text-base text-ink">
|
<div className="font-serif text-sm sm:text-base text-ink leading-snug">
|
||||||
{c.en}
|
{c.en}
|
||||||
</div>
|
</div>
|
||||||
<div className="font-mono text-xs text-ink-mute">
|
<div className="font-mono text-xs text-ink-mute">
|
||||||
@@ -66,8 +64,9 @@ export default function LecturesPage() {
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="pt-3 border-t border-line/60 font-mono text-xs text-ink-mute">
|
<div className="pt-3 border-t border-line/60 font-mono text-xs text-ink-mute flex justify-between items-center">
|
||||||
Course Count: {sem.courses.length}
|
<span>Total Offerings</span>
|
||||||
|
<span className="font-semibold text-ink">{sem.courses.length} Courses</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
@@ -75,30 +74,30 @@ export default function LecturesPage() {
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Older Semesters (Native <details>/<summary> progressive disclosure) */}
|
{/* Older Semesters (Native <details>/<summary> progressive disclosure) */}
|
||||||
<section className="space-y-6 pt-6 border-t border-line">
|
<section className="space-y-6 pt-6 md:pt-8 border-t border-line">
|
||||||
<details className="group border border-line rounded-lg bg-paper p-6 transition-all duration-200">
|
<details className="group border border-line rounded-lg bg-paper p-5 sm:p-6 transition-all duration-200">
|
||||||
<summary className="flex justify-between items-center cursor-pointer list-none select-none">
|
<summary className="flex justify-between items-center cursor-pointer list-none select-none">
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<span className="font-serif text-xl font-normal text-ink">
|
<span className="font-serif text-lg sm:text-xl font-normal text-ink">
|
||||||
이전 전체 강의 이력 ({olderSemesters.length}개 학기) 열람하기
|
Browse all semesters
|
||||||
</span>
|
</span>
|
||||||
<p className="text-xs text-ink-mute font-mono">
|
<p className="text-xs text-ink-mute font-mono">
|
||||||
2016 Fall ~ 2024 Spring 학기별 개설 교과목 이력
|
Course history from {oldestSem ? `${oldestSem.year} ${oldestSem.term}` : "2004 Spring"} to {newestOlderSem ? `${newestOlderSem.year} ${newestOlderSem.term}` : "2024 Fall"} ({olderSemesters.length} Semesters)
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<span className="font-mono text-xs text-vermillion-dark font-bold border border-vermillion-dark px-3 py-1.5 rounded group-open:bg-vermillion-dark group-open:text-white dark:group-open:text-ivory transition-colors">
|
<span className="font-mono text-xs text-vermillion-dark font-bold border border-vermillion-dark px-3.5 py-1.5 rounded group-open:bg-vermillion-dark group-open:text-white dark:group-open:text-ivory transition-colors">
|
||||||
<span className="group-open:hidden">전체 보기 ▾</span>
|
<span className="group-open:hidden">Open ▾</span>
|
||||||
<span className="hidden group-open:inline">접기 ▴</span>
|
<span className="hidden group-open:inline">Close ▴</span>
|
||||||
</span>
|
</span>
|
||||||
</summary>
|
</summary>
|
||||||
|
|
||||||
<div className="mt-6 pt-6 border-t border-line grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
<div className="mt-6 pt-6 border-t border-line grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-5 sm:gap-6">
|
||||||
{olderSemesters.map((sem, idx) => (
|
{olderSemesters.map((sem, idx) => (
|
||||||
<div
|
<div
|
||||||
key={idx}
|
key={idx}
|
||||||
className="bg-ivory p-5 rounded border border-line space-y-3"
|
className="bg-ivory p-5 rounded-lg border border-line space-y-3 shadow-sm hover:border-cobalt-dark/40 transition-colors"
|
||||||
>
|
>
|
||||||
<div className="font-serif text-lg font-normal text-ink border-b border-line pb-1.5 flex justify-between">
|
<div className="font-serif text-base sm:text-lg font-normal text-ink border-b border-line pb-2 flex justify-between items-center">
|
||||||
<span>
|
<span>
|
||||||
{sem.term} {sem.year}
|
{sem.term} {sem.year}
|
||||||
</span>
|
</span>
|
||||||
@@ -110,7 +109,7 @@ export default function LecturesPage() {
|
|||||||
<ul className="space-y-2">
|
<ul className="space-y-2">
|
||||||
{sem.courses.map((c, cIdx) => (
|
{sem.courses.map((c, cIdx) => (
|
||||||
<li key={cIdx} className="space-y-0.5">
|
<li key={cIdx} className="space-y-0.5">
|
||||||
<div className="font-serif text-sm text-ink">
|
<div className="font-serif text-sm text-ink leading-snug">
|
||||||
{c.en}
|
{c.en}
|
||||||
</div>
|
</div>
|
||||||
<div className="font-mono text-[0.7rem] text-ink-mute">
|
<div className="font-mono text-[0.7rem] text-ink-mute">
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
import type { Metadata } from "next";
|
||||||
import { activeMembers, alumni } from "../../content/members";
|
import { activeMembers, alumni } from "../../content/members";
|
||||||
import { ProfessorDetailsDialog } from "./_components/ProfessorDetailsDialog";
|
import { ProfessorDetailsDialog } from "./_components/ProfessorDetailsDialog";
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: "Members",
|
||||||
|
description: "AI Agent Networking Lab (ANL) professor, active researchers, and alumni directory",
|
||||||
|
};
|
||||||
|
|
||||||
const DEGREE_LABEL: Record<string, string> = {
|
const DEGREE_LABEL: Record<string, string> = {
|
||||||
Professor: "Professor",
|
Professor: "Professor",
|
||||||
PhD: "Ph. D.",
|
PhD: "Ph. D.",
|
||||||
@@ -24,16 +30,16 @@ export default function MembersPage() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container-content py-8 sm:py-12 space-y-12 sm:space-y-16">
|
<div className="container-content py-8 sm:py-12 space-y-10 sm:space-y-14">
|
||||||
{/* Page Header */}
|
{/* Page Header */}
|
||||||
<section>
|
<section>
|
||||||
<h1 className="font-serif text-4xl sm:text-5xl font-normal text-ink">
|
<h1 className="font-serif text-4xl sm:text-5xl font-normal text-ink tracking-tight">
|
||||||
LAB MEMBERS
|
LAB MEMBERS
|
||||||
</h1>
|
</h1>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Professor Section */}
|
{/* Professor Section */}
|
||||||
<section className="space-y-6 pt-6 md:pt-10 border-t border-line">
|
<section className="space-y-6 pt-6 md:pt-8 border-t border-line">
|
||||||
<div className="bg-paper p-8 rounded-lg border border-line grid grid-cols-1 lg:grid-cols-12 gap-8 items-center">
|
<div className="bg-paper p-8 rounded-lg border border-line grid grid-cols-1 lg:grid-cols-12 gap-8 items-center">
|
||||||
<div className="lg:col-span-8 space-y-4">
|
<div className="lg:col-span-8 space-y-4">
|
||||||
<h2 className="font-serif text-3xl font-normal text-ink">
|
<h2 className="font-serif text-3xl font-normal text-ink">
|
||||||
@@ -77,10 +83,10 @@ export default function MembersPage() {
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Active Researchers Section */}
|
{/* Active Researchers Section */}
|
||||||
<section className="space-y-8 pt-6 md:pt-10 border-t border-line">
|
<section className="space-y-8 pt-6 md:pt-8 border-t border-line">
|
||||||
<div className="flex justify-between items-end">
|
<div className="flex justify-between items-end">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="font-serif text-3xl font-normal text-cobalt-dark">
|
<h2 className="font-serif text-2xl sm:text-3xl font-normal text-cobalt-dark">
|
||||||
Active Researchers
|
Active Researchers
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
@@ -148,10 +154,10 @@ export default function MembersPage() {
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Alumni Section (Native <details>/<summary> progressive disclosure) */}
|
{/* Alumni Section (Native <details>/<summary> progressive disclosure) */}
|
||||||
<section className="space-y-6 pt-6 md:pt-10 border-t border-line">
|
<section className="space-y-6 pt-6 md:pt-8 border-t border-line">
|
||||||
<div className="flex justify-between items-end">
|
<div className="flex justify-between items-end">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="font-serif text-3xl font-normal text-ink">
|
<h2 className="font-serif text-2xl sm:text-3xl font-normal text-ink">
|
||||||
Graduates
|
Graduates
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ export default function HomePage() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="font-mono text-xs text-ink-mute uppercase tracking-wider mt-1 leading-tight">
|
<div className="font-mono text-xs text-ink-mute uppercase tracking-wider mt-1 leading-tight">
|
||||||
Patent<br />
|
Patent<br />
|
||||||
<span className="text-[0.68rem] tracking-normal font-sans normal-case text-ink-mute/80">
|
<span className="text-[0.68rem] tracking-normal font-sans normal-case text-ink-mute">
|
||||||
(IoT Architecture & Protocols)
|
(IoT Architecture & Protocols)
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
import type { Metadata } from "next";
|
||||||
import { notFound } from "next/navigation";
|
import { notFound } from "next/navigation";
|
||||||
import { CategoryNav } from "../_components/CategoryNav";
|
import { CategoryNav } from "../_components/CategoryNav";
|
||||||
import { publications, patents } from "../../../content/publications";
|
import { publications, patents } from "../../../content/publications";
|
||||||
@@ -11,6 +12,17 @@ interface PageProps {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function generateMetadata({ params }: PageProps): Metadata {
|
||||||
|
const currentCat = PUB_CATEGORIES.find((c) => c.slug === params.category);
|
||||||
|
if (!currentCat) {
|
||||||
|
return { title: "Publications" };
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
title: `${currentCat.label} | Publications`,
|
||||||
|
description: `AI Agent Networking Lab (ANL) ${currentCat.label} research inventory and records`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// SSG static pre-rendering (● SSG) for Next.js 14
|
// SSG static pre-rendering (● SSG) for Next.js 14
|
||||||
export function generateStaticParams() {
|
export function generateStaticParams() {
|
||||||
return PUB_CATEGORIES.map((cat) => ({
|
return PUB_CATEGORIES.map((cat) => ({
|
||||||
@@ -55,44 +67,39 @@ export default function PublicationCategoryPage({ params }: PageProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container-content space-y-8 md:space-y-12 pt-10 md:pt-16 pb-16 md:pb-24">
|
<div className="container-content py-8 sm:py-12 space-y-10 sm:space-y-14">
|
||||||
{/* Header */}
|
{/* Page Header */}
|
||||||
<section className="space-y-3">
|
<section className="space-y-1">
|
||||||
<div className="flex items-center gap-3">
|
<h1 className="font-serif text-4xl sm:text-5xl font-normal text-ink tracking-tight">
|
||||||
<span className="h-px w-8 bg-cobalt-dark"></span>
|
|
||||||
<span className="font-mono text-xs tracking-widest uppercase text-cobalt-dark font-bold">
|
|
||||||
Publications Category
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<h1 className="font-serif text-4xl sm:text-5xl font-normal text-ink">
|
|
||||||
{currentCat.label}
|
{currentCat.label}
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-ink-mute text-base max-w-2xl">
|
{currentCat.subtitle && (
|
||||||
{currentCat.desc} — 총 {records.length}건의 실데이터 카탈로그입니다.
|
<p className="font-mono text-sm text-ink-mute">
|
||||||
</p>
|
{currentCat.subtitle}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Category Nav */}
|
{/* Category Nav Cards */}
|
||||||
<CategoryNav currentCategory={slug} />
|
<section className="pt-6 md:pt-8 border-t border-line">
|
||||||
|
<CategoryNav currentCategory={slug} />
|
||||||
|
</section>
|
||||||
|
|
||||||
{/* Record List Section */}
|
{/* Record List Section */}
|
||||||
<section className="space-y-6">
|
<section className="space-y-6 pt-6 md:pt-8 border-t border-line">
|
||||||
<div className="flex justify-between items-center border-b border-line pb-3">
|
<div className="flex justify-between items-center border-b border-line pb-3">
|
||||||
<span className="font-mono text-xs text-ink-mute uppercase">
|
<span className="font-mono text-xs text-ink-mute uppercase">
|
||||||
Showing {records.length} Pre-rendered Records
|
{records.length} Records
|
||||||
</span>
|
|
||||||
<span className="font-mono text-xs text-vermillion-dark font-bold">
|
|
||||||
SSG ● Static HTML
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{records.length === 0 ? (
|
{records.length === 0 ? (
|
||||||
<div className="bg-paper p-8 rounded-lg border border-line text-center space-y-3">
|
<div className="bg-paper p-8 rounded-lg border border-line text-center space-y-3">
|
||||||
<p className="font-serif text-lg text-ink">
|
<p className="font-serif text-lg text-ink">
|
||||||
현재 등록된 실적이 0건입니다.
|
No records found in this category.
|
||||||
</p>
|
</p>
|
||||||
<p className="text-xs text-ink-mute font-mono">
|
<p className="text-xs text-ink-mute font-mono">
|
||||||
(D-01 카테고리 정류 확정 후 후속 배치가 수행됩니다)
|
Records will be updated periodically.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
@@ -116,13 +123,13 @@ export default function PublicationCategoryPage({ params }: PageProps) {
|
|||||||
|
|
||||||
{rec.isPatent ? (
|
{rec.isPatent ? (
|
||||||
<div className="space-y-1 text-xs text-ink-mute font-mono">
|
<div className="space-y-1 text-xs text-ink-mute font-mono">
|
||||||
<p className="text-ink">발명자: {rec.inventors}</p>
|
<p className="text-ink">Inventors: {rec.inventors}</p>
|
||||||
<p>
|
<p>
|
||||||
출원번호: {rec.appNo} ({rec.country}, {rec.appDate})
|
App No: {rec.appNo} ({rec.country}, {rec.appDate})
|
||||||
</p>
|
</p>
|
||||||
{rec.regNo && (
|
{rec.regNo && (
|
||||||
<p className="text-cobalt-dark font-bold">
|
<p className="text-cobalt-dark font-bold">
|
||||||
등록번호: {rec.regNo} ({rec.regDate})
|
Reg No: {rec.regNo} ({rec.regDate})
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -133,7 +140,7 @@ export default function PublicationCategoryPage({ params }: PageProps) {
|
|||||||
<span>{rec.volume}</span>
|
<span>{rec.volume}</span>
|
||||||
{rec.kci && (
|
{rec.kci && (
|
||||||
<span className="bg-cobalt-dark text-ivory text-[0.65rem] px-1.5 py-0.5 rounded font-bold">
|
<span className="bg-cobalt-dark text-ivory text-[0.65rem] px-1.5 py-0.5 rounded font-bold">
|
||||||
KCI 등재
|
KCI Indexed
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { PUB_CATEGORIES } from "../../../content/categories";
|
import { PUB_CATEGORIES } from "../../../content/categories";
|
||||||
|
import { publications, patents } from "../../../content/publications";
|
||||||
import { PubCategory } from "../../../content/types";
|
import { PubCategory } from "../../../content/types";
|
||||||
|
|
||||||
interface CategoryNavProps {
|
interface CategoryNavProps {
|
||||||
@@ -8,23 +9,94 @@ interface CategoryNavProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function CategoryNav({ currentCategory }: CategoryNavProps) {
|
export function CategoryNav({ currentCategory }: CategoryNavProps) {
|
||||||
|
const getCount = (slug: string) => {
|
||||||
|
if (slug === "patent") return patents.length;
|
||||||
|
return publications.filter((p) => p.category === slug).length;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex flex-wrap items-center gap-2 border-b border-line pb-4">
|
<div className="flex justify-between items-center">
|
||||||
|
<h2 className="font-serif text-2xl sm:text-3xl font-normal text-cobalt-dark">
|
||||||
|
Categories
|
||||||
|
</h2>
|
||||||
|
{currentCategory && (
|
||||||
|
<Link
|
||||||
|
href="/publications"
|
||||||
|
className="font-mono text-xs text-ink-mute hover:text-ink hover:underline transition-colors"
|
||||||
|
>
|
||||||
|
← Overview
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid gap-5 sm:gap-6 md:grid-cols-3">
|
||||||
{PUB_CATEGORIES.map((cat) => {
|
{PUB_CATEGORIES.map((cat) => {
|
||||||
|
const count = getCount(cat.slug);
|
||||||
const isActive = currentCategory === cat.slug;
|
const isActive = currentCategory === cat.slug;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link
|
<div
|
||||||
key={cat.slug}
|
key={cat.slug}
|
||||||
href={`/publications/${cat.slug}`}
|
className={`flex flex-col justify-between bg-paper p-5 sm:p-6 rounded-lg transition-all ${
|
||||||
className={`px-4 py-2 rounded text-xs font-mono tracking-wider transition-colors ${
|
|
||||||
isActive
|
isActive
|
||||||
? "bg-cobalt-dark text-white dark:text-ivory font-bold"
|
? "border-2 border-cobalt-dark shadow-md"
|
||||||
: "bg-paper text-ink border border-line hover:border-cobalt-dark"
|
: "border border-line shadow-sm hover:border-cobalt-dark/40"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{cat.label}
|
<div className="space-y-3">
|
||||||
</Link>
|
<div className="flex justify-between items-center">
|
||||||
|
<span
|
||||||
|
className={`font-mono text-xs font-bold uppercase tracking-wider ${
|
||||||
|
isActive ? "text-cobalt-dark" : "text-ink-mute"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
Category
|
||||||
|
</span>
|
||||||
|
{isActive && (
|
||||||
|
<span className="font-mono text-[0.65rem] font-bold px-2 py-0.5 rounded bg-cobalt-dark/10 text-cobalt-dark uppercase">
|
||||||
|
Current
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3
|
||||||
|
className={`font-serif text-xl ${
|
||||||
|
isActive ? "text-cobalt-dark font-normal" : "text-ink font-normal"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{cat.label}
|
||||||
|
{cat.subtitle && (
|
||||||
|
<span className="block text-xs font-mono text-ink-mute mt-1 font-normal">
|
||||||
|
{cat.subtitle}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-6 pt-4 border-t border-line flex items-baseline justify-between">
|
||||||
|
<span className="font-display text-3xl font-bold text-ink">
|
||||||
|
{count}
|
||||||
|
<span className="text-xs font-mono text-ink-mute ml-1 font-normal">
|
||||||
|
{cat.slug === "patent" ? "Patents" : "Papers"}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
{isActive ? (
|
||||||
|
<span className="inline-flex items-center text-xs font-bold text-cobalt-dark font-mono">
|
||||||
|
Active View ●
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<Link
|
||||||
|
href={`/publications/${cat.slug}`}
|
||||||
|
aria-label={`View all ${cat.label} records`}
|
||||||
|
className="inline-flex items-center text-xs font-bold text-vermillion-dark hover:underline focus:outline-none focus:ring-1 focus:ring-vermillion-dark rounded"
|
||||||
|
>
|
||||||
|
View All →
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,100 +1,53 @@
|
|||||||
import Link from "next/link";
|
import type { Metadata } from "next";
|
||||||
import { CategoryNav } from "./_components/CategoryNav";
|
import { CategoryNav } from "./_components/CategoryNav";
|
||||||
import { PUB_CATEGORIES } from "../../content/categories";
|
import { publications } from "../../content/publications";
|
||||||
import { publications, patents } from "../../content/publications";
|
|
||||||
|
|
||||||
export const metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Publications Overview | ANL",
|
title: "Publications",
|
||||||
description: "AI 에이전트 네트워크 연구실(ANL) 연구 실적 개요 및 카테고리별 집계",
|
description: "AI Agent Networking Lab (ANL) research publications and patents overview",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const REPRESENTATIVE_HIGHLIGHT_TITLES = [
|
||||||
|
"Globally Integrated Trust Authority (GITA) for Resource-Constrained Edge Devices in IoT and 6G",
|
||||||
|
"Application Level Trust Authority (APPLETA) for Resource-Constrained Edge Devices in IoT and 6G",
|
||||||
|
"mQUIC: Use of QUIC for Handover Support with Connection Migration in Wireless/Mobile Networks",
|
||||||
|
"Use of QUIC for CoAP Transport in IoT Networks",
|
||||||
|
"Use of QUIC for Mobile-Oriented Future Internet (Q-MOFI)",
|
||||||
|
];
|
||||||
|
|
||||||
export default function PublicationsIndexPage() {
|
export default function PublicationsIndexPage() {
|
||||||
const totalPubCount = publications.length + patents.length;
|
// Selected 5 representative publications
|
||||||
|
const highlights = REPRESENTATIVE_HIGHLIGHT_TITLES.map((title) =>
|
||||||
// Sort publication records by publishedAt descending to select top 10 highlights
|
publications.find(
|
||||||
const top10Highlights = [...publications]
|
(p) => p.title.trim().toLowerCase() === title.trim().toLowerCase()
|
||||||
.sort((a, b) => (b.publishedAt || "").localeCompare(a.publishedAt || ""))
|
)
|
||||||
.slice(0, 10);
|
).filter((p): p is (typeof publications)[0] => Boolean(p));
|
||||||
|
|
||||||
const getCount = (slug: string) => {
|
|
||||||
if (slug === "patent") return patents.length;
|
|
||||||
return publications.filter((p) => p.category === slug).length;
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main className="container-content space-y-8 md:space-y-12 pt-10 md:pt-16 pb-16 md:pb-24">
|
<div className="container-content py-8 sm:py-12 space-y-10 sm:space-y-14">
|
||||||
{/* Header section */}
|
{/* Page Header */}
|
||||||
<section className="space-y-4">
|
<section>
|
||||||
<div className="flex items-center gap-3">
|
<h1 className="font-serif text-4xl sm:text-5xl font-normal text-ink tracking-tight">
|
||||||
<span className="h-px w-8 bg-cobalt-dark" />
|
PUBLICATIONS
|
||||||
<span className="font-mono text-xs font-bold uppercase tracking-widest text-cobalt-dark">
|
|
||||||
BIBLIOGRAPHY & INTELLECTUAL PROPERTY
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<h1 className="headline-ko text-3xl sm:text-4xl text-ink font-bold">
|
|
||||||
연구 실적 개요
|
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-sm sm:text-base text-ink-mute max-w-3xl leading-relaxed">
|
|
||||||
AI 에이전트 네트워크 연구실(ANL)의 학술 논문({publications.length}건)과 특허({patents.length}건)를 포함한 총 {totalPubCount}건의 연구 성과 집계 및 대표 실적 목록입니다.
|
|
||||||
</p>
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Category Navigation */}
|
|
||||||
<CategoryNav />
|
|
||||||
|
|
||||||
{/* Category Summary Cards */}
|
{/* Category Summary Cards */}
|
||||||
<section className="grid gap-6 md:grid-cols-3">
|
<section className="pt-6 md:pt-8 border-t border-line">
|
||||||
{PUB_CATEGORIES.map((cat) => {
|
<CategoryNav />
|
||||||
const count = getCount(cat.slug);
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
key={cat.slug}
|
|
||||||
className="flex flex-col justify-between border border-line bg-paper p-6 rounded-lg transition-colors hover:border-cobalt-dark group"
|
|
||||||
>
|
|
||||||
<div className="space-y-3">
|
|
||||||
<span className="font-mono text-xs text-ink-mute uppercase tracking-wider">
|
|
||||||
Category
|
|
||||||
</span>
|
|
||||||
<h2 className="headline-ko text-xl text-ink font-bold group-hover:text-cobalt-dark transition-colors">
|
|
||||||
{cat.label}
|
|
||||||
</h2>
|
|
||||||
<p className="text-xs text-ink-mute leading-relaxed">
|
|
||||||
{cat.desc}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="mt-6 pt-4 border-t border-line flex items-baseline justify-between">
|
|
||||||
<span className="font-display text-3xl font-bold text-ink">
|
|
||||||
{count}
|
|
||||||
<span className="text-xs font-sans text-ink-mute ml-1 font-normal">건</span>
|
|
||||||
</span>
|
|
||||||
<Link
|
|
||||||
href={`/publications/${cat.slug}`}
|
|
||||||
className="inline-flex items-center text-xs font-bold text-vermillion-dark hover:underline"
|
|
||||||
>
|
|
||||||
전체 보기 →
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Top 10 Highlights Section */}
|
{/* Highlights Section */}
|
||||||
<section className="space-y-6 pt-6 border-t border-line">
|
<section className="space-y-6 pt-6 md:pt-8 border-t border-line">
|
||||||
<div className="flex items-center justify-between">
|
<h2 className="font-serif text-2xl sm:text-3xl font-normal text-cobalt-dark">
|
||||||
<h2 className="headline-ko text-2xl font-bold text-ink">
|
Highlights
|
||||||
최신 대표 실적 (Top 10 Highlights)
|
</h2>
|
||||||
</h2>
|
|
||||||
<span className="font-mono text-xs text-ink-mute">
|
|
||||||
RECENT HIGHLIGHTS
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="divide-y divide-line border border-line bg-ivory rounded-lg overflow-hidden">
|
<div className="divide-y divide-line border border-line bg-paper rounded-lg overflow-hidden shadow-sm">
|
||||||
{top10Highlights.map((pub, idx) => (
|
{highlights.map((pub, idx) => (
|
||||||
<article key={`${pub.category}-${idx}`} className="p-5 hover:bg-paper/50 transition-colors space-y-2">
|
<article key={`${pub.category}-${idx}`} className="p-5 hover:bg-ivory/60 transition-colors space-y-2">
|
||||||
<div className="flex flex-wrap items-center gap-2 text-xs font-mono text-ink-mute">
|
<div className="flex flex-wrap items-center gap-2 text-xs font-mono text-ink-mute">
|
||||||
<span className="px-2 py-0.5 rounded bg-paper border border-line text-ink font-bold">
|
<span className="px-2 py-0.5 rounded bg-ivory border border-line text-ink font-bold">
|
||||||
{pub.publishedAt?.substring(0, 7) || "Recent"}
|
{pub.publishedAt?.substring(0, 7) || "Recent"}
|
||||||
</span>
|
</span>
|
||||||
<span>·</span>
|
<span>·</span>
|
||||||
@@ -102,11 +55,11 @@ export default function PublicationsIndexPage() {
|
|||||||
{pub.doi && (
|
{pub.doi && (
|
||||||
<>
|
<>
|
||||||
<span>·</span>
|
<span>·</span>
|
||||||
<span className="text-vermillion">DOI: {pub.doi}</span>
|
<span className="text-vermillion-dark">DOI: {pub.doi}</span>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<h3 className="font-semibold text-base text-ink leading-snug">
|
<h3 className="font-serif text-base font-normal text-ink leading-snug">
|
||||||
{pub.title}
|
{pub.title}
|
||||||
</h3>
|
</h3>
|
||||||
{pub.authors && (
|
{pub.authors && (
|
||||||
@@ -115,14 +68,14 @@ export default function PublicationsIndexPage() {
|
|||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
{pub.venue && (
|
{pub.venue && (
|
||||||
<p className="text-xs italic text-ink-soft">
|
<p className="text-xs italic text-ink-mute">
|
||||||
{pub.venue}
|
{pub.venue}{pub.volume ? `, ${pub.volume}` : ""}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</article>
|
</article>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,35 +1,26 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
import type { Metadata } from "next";
|
||||||
import { standardsBodies } from "../../content/standards";
|
import { standardsBodies } from "../../content/standards";
|
||||||
|
|
||||||
export default function StandardizationPage() {
|
export const metadata: Metadata = {
|
||||||
const totalDocs = standardsBodies.reduce(
|
title: "Standardization",
|
||||||
(acc, body) =>
|
description: "AI Agent Networking Lab (ANL) international standardization research and contributions",
|
||||||
acc + body.projects.reduce((pAcc, proj) => pAcc + proj.documents.length, 0),
|
};
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
|
export default function StandardizationPage() {
|
||||||
return (
|
return (
|
||||||
<div className="container-content space-y-12 md:space-y-16 pt-10 md:pt-16 pb-16 md:pb-24">
|
<div className="container-content py-8 sm:py-12 space-y-10 sm:space-y-14">
|
||||||
{/* Header */}
|
{/* Page Header */}
|
||||||
<section className="space-y-3">
|
<section>
|
||||||
<div className="flex items-center gap-3">
|
<h1 className="font-serif text-4xl sm:text-5xl font-normal text-ink tracking-tight">
|
||||||
<span className="h-px w-8 bg-cobalt-dark"></span>
|
International Standardization
|
||||||
<span className="font-mono text-xs tracking-widest uppercase text-cobalt-dark font-bold">
|
|
||||||
Open Standards & Contributions
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<h1 className="font-serif text-4xl sm:text-5xl font-normal text-ink">
|
|
||||||
표준화 연구 및 기여
|
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-ink-mute text-base max-w-2xl">
|
|
||||||
IEC TC100, ISO/IEC JTC1, ITU-T, TTA 등 국제/국내 표준화 기구를 통해 제정 및 진행 중인 {standardsBodies.length}개 기구 {totalDocs}건의 표준 규격 문서 계층 인벤토리입니다.
|
|
||||||
</p>
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Standards Bodies Section */}
|
{/* Standards Bodies Section */}
|
||||||
<section className="space-y-12 pt-6 md:pt-10 border-t border-line">
|
<section className="space-y-8 sm:space-y-10 pt-6 md:pt-8 border-t border-line">
|
||||||
{standardsBodies.map((body, idx) => (
|
{standardsBodies.map((body, idx) => (
|
||||||
<div key={idx} className="bg-paper p-8 rounded-lg border border-line space-y-6">
|
<div key={idx} className="bg-paper p-6 sm:p-8 rounded-lg border border-line space-y-6 shadow-sm">
|
||||||
<div className="flex flex-wrap justify-between items-start gap-4 border-b border-line pb-4">
|
<div className="flex flex-wrap justify-between items-start gap-4 border-b border-line pb-4">
|
||||||
<div>
|
<div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
@@ -103,7 +94,7 @@ export default function StandardizationPage() {
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="text-xs text-ink-mute font-mono italic">
|
<div className="text-xs text-ink-mute font-mono italic">
|
||||||
진행 중인 주 프로젝트 규격서
|
Project specification in progress
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ export default function Footer() {
|
|||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
className="inline-flex items-center gap-1 px-2.5 py-1 rounded bg-ivory border border-line text-ink-soft hover:text-cobalt-dark hover:border-cobalt/40 transition-colors"
|
className="inline-flex items-center gap-1 px-2.5 py-1 rounded bg-ivory border border-line text-ink-soft hover:text-cobalt-dark hover:border-cobalt/40 transition-colors"
|
||||||
>
|
>
|
||||||
<span>College of IT Engineering</span>
|
<span>CITE</span>
|
||||||
<span className="text-[0.65rem] text-ink-mute">↗</span>
|
<span className="text-[0.65rem] text-ink-mute">↗</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ export default function Header() {
|
|||||||
{/* Brand logo */}
|
{/* Brand logo */}
|
||||||
<Link
|
<Link
|
||||||
href="/"
|
href="/"
|
||||||
className="group flex items-center gap-3 shrink-0"
|
className="group flex items-center gap-3 min-w-0 desktop:shrink-0"
|
||||||
onClick={() => setOpen(false)}
|
onClick={() => setOpen(false)}
|
||||||
>
|
>
|
||||||
<div className="relative flex items-center justify-center w-9 h-9 sm:w-10 sm:h-10 rounded-xl overflow-hidden shadow-sm ring-1 ring-ink/10 group-hover:ring-cobalt/40 group-hover:shadow-md group-hover:scale-105 transition-all duration-300 shrink-0">
|
<div className="relative flex items-center justify-center w-9 h-9 sm:w-10 sm:h-10 rounded-xl overflow-hidden shadow-sm ring-1 ring-ink/10 group-hover:ring-cobalt/40 group-hover:shadow-md group-hover:scale-105 transition-all duration-300 shrink-0">
|
||||||
@@ -158,11 +158,11 @@ export default function Header() {
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col leading-none">
|
<div className="flex flex-col leading-none min-w-0">
|
||||||
<span className="headline-ko text-lg text-ink sm:text-xl font-bold tracking-tight group-hover:text-cobalt-dark transition-colors">
|
<span className="headline-ko text-lg text-ink sm:text-xl font-bold tracking-tight group-hover:text-cobalt-dark transition-colors">
|
||||||
ANL
|
ANL
|
||||||
</span>
|
</span>
|
||||||
<span className="kicker mt-1 transition-colors group-hover:text-cobalt-dark">
|
<span className="kicker mt-1 transition-colors group-hover:text-cobalt-dark truncate">
|
||||||
AI Agent Networking LAB
|
AI Agent Networking LAB
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { PubCategory } from "./types";
|
|||||||
export interface CategoryInfo {
|
export interface CategoryInfo {
|
||||||
slug: PubCategory;
|
slug: PubCategory;
|
||||||
label: string;
|
label: string;
|
||||||
|
subtitle?: string;
|
||||||
desc: string;
|
desc: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,6 +22,7 @@ export const PUB_CATEGORIES: CategoryInfo[] = [
|
|||||||
{
|
{
|
||||||
slug: "patent",
|
slug: "patent",
|
||||||
label: "Patent",
|
label: "Patent",
|
||||||
|
subtitle: "(IoT Architecture & Protocols, etc ...)",
|
||||||
desc: "국내외 지식재산권 출원 및 등록 실적",
|
desc: "국내외 지식재산권 출원 및 등록 실적",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -121,5 +121,56 @@ class TestANLHomepageE2E(unittest.TestCase):
|
|||||||
# 4. Assert zero placeholder Funder labels (AC-31)
|
# 4. Assert zero placeholder Funder labels (AC-31)
|
||||||
self.assertNotIn("Funder:", html)
|
self.assertNotIn("Funder:", html)
|
||||||
|
|
||||||
|
def test_08_publications_highlights_and_category_nav(self):
|
||||||
|
"""TC-T1-F8: Verify 5 representative highlights and CategoryNav active border in Publications."""
|
||||||
|
html = self.read_html("publications.html")
|
||||||
|
|
||||||
|
# 1. Verify 5 designated representative publications
|
||||||
|
expected_highlights = [
|
||||||
|
"Globally Integrated Trust Authority (GITA) for Resource-Constrained Edge Devices in IoT and 6G",
|
||||||
|
"Application Level Trust Authority (APPLETA) for Resource-Constrained Edge Devices in IoT and 6G",
|
||||||
|
"mQUIC: Use of QUIC for Handover Support with Connection Migration in Wireless/Mobile Networks",
|
||||||
|
"Use of QUIC for CoAP Transport in IoT Networks",
|
||||||
|
"Use of QUIC for Mobile-Oriented Future Internet (Q-MOFI)",
|
||||||
|
]
|
||||||
|
for title in expected_highlights:
|
||||||
|
self.assertIn(title, html, f"Missing representative highlight publication: '{title}'")
|
||||||
|
|
||||||
|
# 2. Verify Highlights heading & section
|
||||||
|
self.assertIn("Highlights", html)
|
||||||
|
self.assertIn("Categories", html)
|
||||||
|
self.assertIn("(IoT Architecture & Protocols, etc ...)", html)
|
||||||
|
|
||||||
|
# 3. Verify category detail active card border & label
|
||||||
|
patent_html = self.read_html(os.path.join("publications", "patent.html"))
|
||||||
|
self.assertIn("border-2 border-cobalt-dark", patent_html)
|
||||||
|
self.assertIn("Active View ●", patent_html)
|
||||||
|
self.assertIn("Patent", patent_html)
|
||||||
|
|
||||||
|
def test_09_footer_cite_and_brand_links(self):
|
||||||
|
"""TC-T1-F9: Verify Footer CITE abbreviation and brand/contact elements."""
|
||||||
|
html = self.read_html("index.html")
|
||||||
|
|
||||||
|
# 1. Institution link label CITE
|
||||||
|
self.assertIn("<span>CITE</span>", html)
|
||||||
|
self.assertIn("<span>KNU</span>", html)
|
||||||
|
self.assertIn("<span>CSE</span>", html)
|
||||||
|
|
||||||
|
# 2. Advisor contact info
|
||||||
|
self.assertIn("Prof. Seok-Joo Koh", html)
|
||||||
|
self.assertIn("sjkoh@knu.ac.kr", html)
|
||||||
|
|
||||||
|
def test_10_subpage_layout_and_english_headers(self):
|
||||||
|
"""TC-T1-F10: Verify English page headers across all subpages."""
|
||||||
|
subpages = [
|
||||||
|
("members.html", "LAB MEMBERS"),
|
||||||
|
("publications.html", "PUBLICATIONS"),
|
||||||
|
("lectures.html", "LECTURES"),
|
||||||
|
("standardization.html", "International Standardization"),
|
||||||
|
]
|
||||||
|
for rel_path, expected_h1 in subpages:
|
||||||
|
html = self.read_html(rel_path)
|
||||||
|
self.assertIn(expected_h1, html, f"Subpage {rel_path} missing H1 '{expected_h1}'")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
@@ -7,10 +7,10 @@
|
|||||||
# - .mam.env present --force → overwrite .mam.env from .mam.env.example (backs up to .mam.env.bak).
|
# - .mam.env present --force → overwrite .mam.env from .mam.env.example (backs up to .mam.env.bak).
|
||||||
# - --migrate-legacy → explicitly rename existing .env to .mam.env if absent.
|
# - --migrate-legacy → explicitly rename existing .env to .mam.env if absent.
|
||||||
#
|
#
|
||||||
# Paths are resolved relative to this script (repo root = parent of scripts/),
|
# Paths are resolved relative to this script (repo root = parent of deploy/),
|
||||||
# so it works regardless of the caller's cwd.
|
# so it works regardless of the caller's cwd.
|
||||||
#
|
#
|
||||||
# Usage: scripts/generate-env.sh [--force] [--migrate-legacy] [-h|--help]
|
# Usage: deploy/generate-env.sh [--force] [--migrate-legacy] [-h|--help]
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
|||||||
Reference in New Issue
Block a user