Compare commits

48 Commits

Author SHA1 Message Date
admins a8cd2cd4d4 feat: auto-enroll new signups into free course obsidian-start (freemium)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 14:05:52 +05:00
admins 2ea9c6fda0 Don't force password change while admin is impersonating
The mustChangePassword guard redirected an impersonating admin to
/change-password, which sits outside the student layout (no
return-to-admin banner) — a dead end. Skip the guard when impersonating,
and add the stop-impersonate banner to the change-password page as a
fallback.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 11:03:58 +05:00
admins ec011ab7fd Add support mailto on login for missing password-reset email
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 12:58:28 +05:00
admins 27027b134f Use CDN URL for public file links when S3_CDN_URL is set
getPublicUrl returns the CDN URL (files.second-brain.ru via Bunny) when
S3_CDN_URL is configured, falling back to the direct S3 endpoint. This
was a manual patch on the build server that was never committed —
restore it so new uploads also get CDN-backed (RU-accessible) URLs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 12:46:31 +05:00
admins 04e8377dab Show hint on lessons with pending homework or quiz
Lessons with homework/quiz have no manual complete button — they
auto-complete on submission. Before submission nothing was shown,
leaving students unsure how to progress. Add a muted hint.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 12:22:44 +05:00
admins 5d4630519c Force download for lesson materials (Content-Disposition: attachment)
Lesson files were served inline (no Content-Disposition) → browsers
opened PDFs in a new tab instead of downloading; flaky across
browsers/providers. Set Content-Disposition: attachment with the
human-readable filename (RFC 5987 for Cyrillic) on upload.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 16:06:51 +05:00
admins a7abf454d9 Add internal grant endpoint + temp-password / force-change flow
- /api/internal/grant: secret-auth endpoint for payment-router to
  provision access on a paid order — find-or-create user (emailVerified,
  temp password, mustChangePassword), enroll by course slug list,
  AccessLog, delivery email. Idempotent by order_id.
- User.mustChangePassword flag (+ migration); (student) layout redirects
  flagged users to /change-password (forced first-login change).
- email.ts: sendCourseGrantEmail (temp password for new buyers).
- middleware: /api/internal is public (own secret auth).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 16:25:35 +05:00
admins 5a67ac8086 Close captcha-bypass and email-abuse vectors
- Block direct /api/auth/sign-up at the middleware (404): it bypassed
  the Turnstile/honeypot wrapper. /api/register is unaffected — it
  invokes auth.handler programmatically, not through HTTP.
- Tighten rate limits on send-verification-email and forget-password
  (3/min/IP): both send emails to arbitrary addresses and shared the
  loose global 100/min limit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 14:18:30 +05:00
admins 85cf8be705 Explicitly resend verification email on unverified login
Better Auth does not auto-resend on 403 (verified against Resend logs),
so request a fresh link via authClient.sendVerificationEmail before
telling the user a new email was sent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 14:05:32 +05:00
admins 2790a7d24b Wire up email verification flow for new signups
requireEmailVerification was enabled but no sendVerificationEmail was
configured — new users saw "check your email", never received anything,
and couldn't log in (403 shown as "wrong email or password").

- email.ts: add verification email template; welcome email no longer
  claims the account is "confirmed"
- auth.ts: configure emailVerification (send on signup, resend on
  unverified login attempt, auto sign-in after verification, 24h TTL)
- register route: callbackURL=/dashboard so the verify link lands in
  the cabinet
- login form: distinguish 403 (unverified — tell user a fresh link was
  sent) and 429 (rate limit) from wrong credentials

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 14:01:46 +05:00
admins 619ae393bd Allow /api/register through auth middleware
The Turnstile/honeypot wrapper /api/register was missing from
PUBLIC_ROUTES, so unauthenticated POSTs were redirected to /login (307).
The register form followed the redirect, got HTML, and failed to parse
it — surfacing as "connection error". This silently broke signups for
new users. Add /api/register alongside /api/auth.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 13:26:19 +05:00
admins 8240db5d22 Make registration errors informative
- Backend: explicitly return 409 EMAIL_TAKEN when the email already
  exists, instead of Better Auth's silent 200 (common after migration).
- Frontend: split error handling — network failure, non-JSON body
  (502/proxy), and meaningful server errors get distinct messages; the
  "email already registered" case shows login / reset-password links
  instead of a generic "connection error".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 13:20:56 +05:00
admins 05f46ec830 Add "login as user" to user profile card
Extract ImpersonateButton into a shared component and reuse it on the
admin user profile page (header, hidden for admins) — same behaviour as
the users list.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 15:55:57 +05:00
admins 3b8a1ce7ee Link question author name to their admin profile
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 10:53:01 +05:00
admins a290b9495c Enroll modal: days input instead of date; hide bundle if base course owned
- Quick-enroll modal now takes access duration in days (0/empty = unlimited)
  and shows the computed expiry date, instead of a manual date picker.
- Dashboard upsell no longer shows the "Всё включено" bundle of a course
  the student already owns in its base edition (obsidian/zotero).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 16:13:15 +05:00
admins 8c9f1e0a55 Add mobile spacer so admin content clears the hamburger button
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 10:01:58 +05:00
admins ffc5905309 Make admin/curator sidebar collapsible on mobile
The admin shell sidebar was always fixed at 208px with no mobile
handling, so on phones it covered half the screen with no way to hide
it. Add a hamburger toggle + overlay (mirroring the student course
sidebar): off-canvas on <lg, sticky as before on desktop.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 09:58:15 +05:00
admins 3ed5540f40 Reduce blur on locked course cards for readability
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 16:06:32 +05:00
admins 7dc3412903 Add locked course cards (upsell) to student dashboard
Show the sellable course lineup on the dashboard: courses the student
doesn't own render as blurred cards with a lock and a CTA linking to the
product landing page (new tab). Owned courses are unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 16:01:39 +05:00
admins 7c85a7835b Widen dashboard course cards and enlarge title/description text 2026-06-04 10:32:30 +05:00
admins ecf48de7e8 Copy code block verbatim (fences live in content for Obsidian snippets) 2026-06-03 15:34:15 +05:00
admins ecbca89cef Copy full markdown fence for language-tagged code blocks (dataview/query) 2026-06-03 15:23:27 +05:00
admins cf942d223e Mark lesson complete on homework submit; add copy button + styling to code blocks 2026-06-03 14:58:30 +05:00
admins adc1d6fc06 Loosen sign-in rate limit to 10/min per IP for migration onboarding 2026-06-03 14:03:11 +05:00
admins 6624a0c535 Restore list markers (disc/decimal) for lesson content lists 2026-06-03 13:34:11 +05:00
admins a65125a239 Linkify URLs and preserve line breaks in question messages 2026-05-27 14:16:25 +05:00
admins 14b1eacf0d Switch homework pending filter from feedbacks-none to status-based (PENDING/REVIEWING) 2026-05-27 11:59:25 +05:00
admins d9e3531c49 Apply lesson cover as poster for embedded kinescopeVideo nodes 2026-05-26 16:40:47 +05:00
admins 5e5f616888 debug: move banner outside kinescopeId block to catch null ID 2026-05-26 16:22:18 +05:00
admins 4222834539 temp: visible debug banner for coverImage 2026-05-26 16:11:33 +05:00
admins 2525ca2b32 temp: debug coverImage value in lesson page 2026-05-26 15:49:47 +05:00
admins cfd3681979 Fix poster overlay hidden behind Kinescope iframe
Kinescope renders an iframe that ignores z-index stacking.
Switch to mutually-exclusive render: show poster image OR
the player, never both. Click on poster dismisses it and
reveals the player.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 15:40:23 +05:00
admins c2c2190cb6 Show custom lesson cover as video poster overlay
Kinescope React player ignores the poster prop. Replace with a
click-to-dismiss overlay rendered above the player: shows the
lesson coverImage, a play button, and on click hides itself
and calls player.play() via ref.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 15:35:39 +05:00
admins 6542f9b6b6 Add NEXT_PUBLIC_TURNSTILE_SITE_KEY build arg to Dockerfile
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 12:39:46 +05:00
admins 231ed083be Add anti-bot registration protection
- Custom /api/register route: honeypot, disposable email blocking, Cloudflare Turnstile verification
- Register form: honeypot hidden field, Turnstile widget (loads when NEXT_PUBLIC_TURNSTILE_SITE_KEY set)
- Install disposable-email-domains package
- Add NEXT_PUBLIC_TURNSTILE_SITE_KEY and TURNSTILE_SECRET_KEY env vars to .env.example

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 12:35:06 +05:00
admins c1c33a0619 Make links in lesson content visually distinct (underline + bold)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 11:35:07 +05:00
admins 7e6ad8067c Add in-content video embed and image replace/delete controls
- KinescopeVideo TipTap node: insert video anywhere in lesson content via toolbar button; editor shows ID preview, student view renders KinescopePlayer
- ImageWithControls NodeView: hover over any image in editor to reveal Replace and Delete buttons

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 11:27:52 +05:00
admins 287347168d Add cross-module lesson navigation and admin edit button
- Admin lesson editor now navigates across module boundaries (full course flat list)
- Student lesson view shows "Edit" button for admins linking to lesson editor

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 11:05:46 +05:00
admins f3428420e2 Add migration for Session.impersonatedBy column 2026-05-25 16:01:57 +05:00
admins 38267fa432 Add staging environment plan and deploy script
Staging runs at staging.school.second-brain.ru on Hetzner port 3011.
Deploy script: ~/Documents/Claude/scripts/deploy-staging.sh

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 15:13:26 +05:00
admins 30405e768b Show last login date on admin user detail page
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 09:37:10 +05:00
admins 3b57b14d9b Add file attachments to questions (new question form + admin reply)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 18:26:17 +05:00
admins 367764b71e Expand /questions/new form: wider container, larger inputs, hint texts
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 18:10:33 +05:00
admins acf7ee49aa Replace single-line reply input with resizable textarea in QuestionSplitView 2026-05-19 18:01:27 +05:00
admins 751c012f3d Add /admin/comments page with delete and pagination
- Add admin auth guard (redirect to /dashboard if not admin)
- Add delete-action.ts with deleteComment(commentId) soft-delete action
- Fix pagination label to show "Страница X из Y · Всего: N"
- Existing actions.ts, comments-table.tsx, and admin-nav entry preserved

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 14:31:38 +05:00
admins 7084806aac Add search, filters, pagination to homework list
- Replace client HomeworkFilters component with server-side <form method="GET">
- Switch search param from `search` to `q`, add lesson title to search scope
- Change status filter from DB status field to feedback-count logic (pending=no feedbacks, reviewed=has feedbacks)
- Update pagination label to "Страница X из Y · Всего: N"
- Preserve all existing submission links and layout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 14:29:47 +05:00
admins b2fa98051f Add quick enroll button to admin users table
Adds a "+ Доступ" button to each user row in the admin users table.
Clicking it opens a centered modal with a course dropdown, optional
expiry date, and a Server Action that upserts CourseEnrollment, logs
to AccessLog, and sends sendCourseAccessEmail on new enrollments.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 14:27:57 +05:00
admins 4f5b5c535a Add search, filters, pagination to admin users table
- Add emailVerified filter (true/false/any) to UsersSearch component
- Wire emailVerified param through page searchParams, where clause, and pageUrl helper
- Preserve emailVerified in pagination links alongside existing search/role/balance params
- Update pagination label to "Страница X из Y · Всего: N"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 14:25:53 +05:00
292 changed files with 23927 additions and 185 deletions
+12 -2
View File
@@ -12,5 +12,15 @@ S3_ACCESS_KEY=""
S3_SECRET_KEY="" S3_SECRET_KEY=""
S3_REGION="eu-central" S3_REGION="eu-central"
# Kinescope (добавить при получении платного плана) # Cloudflare Turnstile (anti-bot защита на регистрации)
# KINESCOPE_API_KEY="" NEXT_PUBLIC_TURNSTILE_SITE_KEY=""
TURNSTILE_SECRET_KEY=""
# Kinescope API
KINESCOPE_API_KEY=""
# Internal access-provisioning (payment-router → /api/internal/grant)
INTERNAL_GRANT_SECRET=""
# Freemium: slug бесплатного курса, в который авто-записываем новых юзеров при регистрации
FREE_COURSE_SLUG=obsidian-start
+11
View File
@@ -0,0 +1,11 @@
# Auto-generated Prisma client — раздувает граф 28 псевдо-сообществами
src/generated/
# Superpowers / Claude Code инфраструктура, к LMS-коду не относится
.claude/
# Build/cache артефакты (на всякий случай, помимо .gitignore)
.next/
out/
build/
coverage/
View File
@@ -0,0 +1,86 @@
<h2>Как выглядит раздел «Вопросы» в админке?</h2>
<p class="subtitle">Список + открытый тред — выбери что ближе по ощущению</p>
<div class="options">
<div class="option" data-choice="a" onclick="toggleSelect(this)">
<div class="letter">A</div>
<div class="content">
<h3>Список + боковая панель треда</h3>
<p>Слева список вопросов, справа открывается тред. Как почтовый клиент — не уходишь со страницы.</p>
<div class="mockup" style="margin-top:12px">
<div class="mockup-header">Admin → Вопросы учеников</div>
<div class="mockup-body" style="padding:0; display:flex; min-height:160px; font-size:12px">
<div style="width:45%; border-right:2px solid #AAAAAA; padding:8px">
<div style="margin-bottom:6px; display:flex; gap:4px">
<span style="padding:2px 8px; background:#323232; color:#F5F5F0; border-radius:2px; font-size:10px">Открытые 4</span>
<span style="padding:2px 8px; background:#E8E8E0; border-radius:2px; font-size:10px">Закрытые</span>
</div>
<div style="padding:6px; background:#E8F0D8; border-left:3px solid #323232; margin-bottom:4px">
<div style="font-weight:700">Алексей М.</div>
<div style="color:#666; font-size:11px">Как экспортировать в PDF?</div>
<div style="color:#999; font-size:10px">15 мин назад · 🔴 новое</div>
</div>
<div style="padding:6px; background:#F5F5F0; border-left:3px solid transparent; margin-bottom:4px; border:1px solid #E8E8E0">
<div>Мария К.</div>
<div style="color:#666; font-size:11px">Плагины не устанавливаются</div>
<div style="color:#999; font-size:10px">2 часа назад</div>
</div>
<div style="padding:6px; background:#F5F5F0; border:1px solid #E8E8E0">
<div>Иван С.</div>
<div style="color:#666; font-size:11px">Синхронизация с телефоном</div>
<div style="color:#999; font-size:10px">вчера · 🔴 новое</div>
</div>
</div>
<div style="flex:1; padding:8px; display:flex; flex-direction:column">
<div style="font-weight:700; margin-bottom:2px; font-size:13px">Как экспортировать в PDF?</div>
<div style="color:#666; font-size:11px; margin-bottom:8px">Алексей М. · Obsidian. Полный курс</div>
<div style="background:#E8E8E0; padding:6px; border-radius:2px; margin-bottom:6px; font-size:12px">
Привет! Пытаюсь экспортировать заметки в PDF через Pandoc, но получаю ошибку...
</div>
<div style="margin-top:auto; display:flex; gap:4px">
<input style="flex:1; padding:4px 6px; border:1px solid #AAAAAA; font-size:11px; border-radius:2px" placeholder="Ответить...">
<button style="padding:4px 8px; background:#323232; color:#F5F5F0; border:none; font-size:11px; border-radius:2px"></button>
<button style="padding:4px 8px; background:#E8E8E0; border:1px solid #AAAAAA; font-size:10px; border-radius:2px">✓ Закрыть</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="option" data-choice="b" onclick="toggleSelect(this)">
<div class="letter">B</div>
<div class="content">
<h3>Список → отдельная страница треда</h3>
<p>Список всех вопросов, клик открывает отдельную страницу. Проще в реализации, больше места для переписки.</p>
<div class="mockup" style="margin-top:12px">
<div class="mockup-header">Admin → Вопросы / #42 — Алексей М.</div>
<div class="mockup-body" style="padding:8px; font-size:12px">
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:8px">
<span style="font-weight:700">Как экспортировать в PDF?</span>
<span style="padding:2px 8px; background:#E8F0D8; border:1px solid #AAAAAA; font-size:10px; border-radius:2px">● ОТКРЫТ</span>
</div>
<div style="display:flex; flex-direction:column; gap:5px; margin-bottom:8px">
<div style="background:#E8E8E0; padding:5px 8px; border-radius:2px; max-width:80%">
<div style="font-size:10px; color:#666">Алексей · 14:32</div>
Пытаюсь экспортировать через Pandoc, получаю ошибку...
</div>
<div style="background:#F5F5F0; border:2px solid #E8F0D8; padding:5px 8px; border-radius:2px; max-width:80%; align-self:flex-end">
<div style="font-size:10px; color:#666">Дмитрий (admin) · 14:55</div>
Покажи текст ошибки?
</div>
<div style="background:#E8E8E0; padding:5px 8px; border-radius:2px; max-width:80%">
<div style="font-size:10px; color:#666">Алексей · 15:01</div>
"Error: pandoc not found in PATH"
</div>
</div>
<div style="display:flex; gap:4px">
<input style="flex:1; padding:4px 6px; border:1px solid #AAAAAA; font-size:11px; border-radius:2px" placeholder="Написать ответ...">
<button style="padding:4px 10px; background:#323232; color:#F5F5F0; border:none; font-size:11px; border-radius:2px">Отправить</button>
<button style="padding:4px 8px; background:#E8E8E0; border:1px solid #AAAAAA; font-size:10px; border-radius:2px">✓ Закрыть вопрос</button>
</div>
</div>
</div>
</div>
</div>
</div>
@@ -0,0 +1,56 @@
<h2>Как устроен диалог после отправки вопроса?</h2>
<p class="subtitle">Влияет на структуру БД и сложность реализации</p>
<div class="options">
<div class="option" data-choice="a" onclick="toggleSelect(this)">
<div class="letter">A</div>
<div class="content">
<h3>Один вопрос → один ответ</h3>
<p>Студент задаёт вопрос. Админ отвечает один раз. Закрыто. Просто и быстро в реализации.</p>
<div class="mockup" style="margin-top:12px">
<div class="mockup-header">Страница вопроса у студента</div>
<div class="mockup-body" style="padding:12px; font-size:13px">
<div style="background:#E8E8E0; padding:8px; border-radius:2px; margin-bottom:8px">
<div style="font-size:11px; color:#666; margin-bottom:4px">Ты · 14 мая</div>
<div>Как правильно настроить шаблоны в Obsidian?</div>
</div>
<div style="background:#E8F0D8; border:2px solid #323232; padding:8px; border-radius:2px">
<div style="font-size:11px; color:#666; margin-bottom:4px">Дмитрий · 15 мая ✅ Отвечено</div>
<div>Зайди в Настройки → Шаблоны → укажи папку...</div>
</div>
</div>
</div>
</div>
</div>
<div class="option" data-choice="b" onclick="toggleSelect(this)">
<div class="letter">B</div>
<div class="content">
<h3>Тред (переписка)</h3>
<p>Студент и админ могут писать несколько сообщений. Как поддержка-чат внутри платформы.</p>
<div class="mockup" style="margin-top:12px">
<div class="mockup-header">Тред вопроса</div>
<div class="mockup-body" style="padding:12px; font-size:13px">
<div style="background:#E8E8E0; padding:6px 8px; border-radius:2px; margin-bottom:6px; margin-left:0; max-width:85%">
<div style="font-size:10px; color:#666">Ты · 14 мая</div>
Как настроить шаблоны?
</div>
<div style="background:#E8F0D8; padding:6px 8px; border-radius:2px; margin-bottom:6px; margin-left:auto; max-width:85%; text-align:right">
<div style="font-size:10px; color:#666">Дмитрий · 15 мая</div>
Зайди в Настройки → Шаблоны...
</div>
<div style="background:#E8E8E0; padding:6px 8px; border-radius:2px; margin-bottom:6px; max-width:85%">
<div style="font-size:10px; color:#666">Ты · 15 мая</div>
А какую папку лучше назвать?
</div>
<div style="border:1px solid #AAAAAA; border-radius:2px; padding:6px 8px; color:#999; font-size:12px">Написать сообщение...</div>
</div>
</div>
</div>
</div>
</div>
<div class="section" style="margin-top:16px; padding:12px; background:#F5F5F0; border:1px solid #AAAAAA; border-radius:2px">
<span class="label">Рекомендация</span>
<p style="margin:4px 0 0; font-size:14px">Вариант А проще, закрывает 90% случаев. Тред (Б) полезен когда ответ требует уточнений, но добавляет ~40% сложности реализации.</p>
</div>
@@ -0,0 +1,56 @@
<h2>Где студент начинает «Задать вопрос»?</h2>
<p class="subtitle">Влияет на то, будет ли вопрос привязан к уроку или нет</p>
<div class="options">
<div class="option" data-choice="a" onclick="toggleSelect(this)">
<div class="letter">A</div>
<div class="content">
<h3>Только главное меню</h3>
<p>Пункт «Задать вопрос» в хедере / sidebar студента. Общий вопрос без привязки к уроку.</p>
<div class="mockup" style="margin-top:12px">
<div class="mockup-header">Студент — sidebar</div>
<div class="mockup-body" style="padding:12px; font-size:13px">
<div style="padding:8px; margin-bottom:4px; background:#E8E8E0; border-radius:2px">📚 Мои курсы</div>
<div style="padding:8px; margin-bottom:4px; background:#E8E8E0; border-radius:2px">👤 Профиль</div>
<div style="padding:8px; background:#E8F0D8; border:2px solid #323232; border-radius:2px; font-weight:700">❓ Задать вопрос</div>
</div>
</div>
</div>
</div>
<div class="option" data-choice="b" onclick="toggleSelect(this)">
<div class="letter">B</div>
<div class="content">
<h3>Только со страницы урока</h3>
<p>Кнопка на странице урока рядом с комментариями. Вопрос автоматически привязан к курсу и уроку.</p>
<div class="mockup" style="margin-top:12px">
<div class="mockup-header">Страница урока — низ</div>
<div class="mockup-body" style="padding:12px; font-size:13px">
<div style="margin-bottom:8px; color:#666">💬 Комментарии (3)</div>
<div style="display:flex; gap:8px">
<div style="padding:6px 12px; background:#E8E8E0; border:1px solid #AAAAAA; border-radius:2px; font-size:12px">Написать комментарий</div>
<div style="padding:6px 12px; background:#F5F5F0; border:2px solid #323232; border-radius:2px; font-size:12px; font-weight:700">❓ Задать приватный вопрос</div>
</div>
</div>
</div>
</div>
</div>
<div class="option" data-choice="c" onclick="toggleSelect(this)">
<div class="letter">C</div>
<div class="content">
<h3>Оба места</h3>
<p>Пункт в меню для общих вопросов + кнопка на уроке для вопросов по конкретному уроку. Контекст подставляется автоматически.</p>
<div class="mockup" style="margin-top:12px">
<div class="mockup-header">Два источника → одна очередь у админа</div>
<div class="mockup-body" style="padding:12px; font-size:13px">
<div style="display:flex; gap:8px; margin-bottom:8px">
<div style="padding:6px 10px; background:#E8F0D8; border:2px solid #323232; font-size:11px; font-weight:700; border-radius:2px">Меню → общий вопрос</div>
<div style="padding:6px 10px; background:#E8F0D8; border:2px solid #323232; font-size:11px; font-weight:700; border-radius:2px">Урок → вопрос по уроку</div>
</div>
<div style="padding:8px; border:1px solid #AAAAAA; border-radius:2px; color:#666; font-size:12px">→ Один список у админа: «Вопросы учеников»</div>
</div>
</div>
</div>
</div>
</div>
@@ -0,0 +1,108 @@
<h2>Студент — раздел «Мои вопросы»</h2>
<p class="subtitle">Список + открытый тред. Скажи что поправить.</p>
<div class="split" style="gap:16px; align-items:flex-start">
<!-- Список вопросов -->
<div class="mockup" style="flex:1">
<div class="mockup-header">/questions — Мои вопросы</div>
<div class="mockup-body" style="padding:12px; font-size:13px">
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:12px">
<span style="font-weight:700; font-size:15px">Мои вопросы</span>
<button style="padding:6px 14px; background:#F5F5F0; border:2px solid #323232; font-size:12px; font-weight:700; border-radius:2px; cursor:pointer">+ Задать вопрос</button>
</div>
<!-- Открытый вопрос с новым ответом -->
<div style="border:2px solid #323232; border-radius:2px; padding:10px; margin-bottom:8px; background:#F5F5F0; cursor:pointer">
<div style="display:flex; justify-content:space-between; align-items:flex-start; margin-bottom:4px">
<span style="font-weight:700; font-size:13px">Как настроить синхронизацию с телефоном?</span>
<span style="padding:2px 7px; background:#E8F0D8; border:1px solid #AAAAAA; font-size:10px; border-radius:2px; white-space:nowrap; margin-left:8px">● ОТКРЫТ</span>
</div>
<div style="color:#666; font-size:11px; margin-bottom:6px">3 сообщения · последнее от Дмитрия</div>
<div style="display:flex; align-items:center; gap:6px">
<span style="display:inline-block; width:8px; height:8px; background:#323232; border-radius:50%"></span>
<span style="font-size:11px; font-weight:700">Новый ответ от школы</span>
<span style="color:#999; font-size:11px">· 20 мин назад</span>
</div>
</div>
<!-- Обычный открытый вопрос -->
<div style="border:1px solid #AAAAAA; border-radius:2px; padding:10px; margin-bottom:8px; background:#F5F5F0; cursor:pointer">
<div style="display:flex; justify-content:space-between; align-items:flex-start; margin-bottom:4px">
<span style="font-size:13px">Ошибка при установке плагина Dataview</span>
<span style="padding:2px 7px; background:#E8F0D8; border:1px solid #AAAAAA; font-size:10px; border-radius:2px; white-space:nowrap; margin-left:8px">● ОТКРЫТ</span>
</div>
<div style="color:#666; font-size:11px">2 сообщения · ожидает ответа школы</div>
</div>
<!-- Закрытый вопрос -->
<div style="border:1px solid #E8E8E0; border-radius:2px; padding:10px; background:#FAFAFA; cursor:pointer; opacity:0.7">
<div style="display:flex; justify-content:space-between; align-items:flex-start; margin-bottom:4px">
<span style="font-size:13px; color:#666">Как экспортировать заметки в PDF?</span>
<span style="padding:2px 7px; background:#E8E8E0; font-size:10px; border-radius:2px; white-space:nowrap; margin-left:8px; color:#666">✓ ЗАКРЫТ</span>
</div>
<div style="color:#999; font-size:11px">5 сообщений · закрыт 10 мая</div>
</div>
</div>
</div>
<!-- Страница треда -->
<div class="mockup" style="flex:1.2">
<div class="mockup-header">/questions/[id] — Открытый тред</div>
<div class="mockup-body" style="padding:12px; font-size:13px">
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:10px">
<div>
<div style="font-weight:700; font-size:14px">Как настроить синхронизацию с телефоном?</div>
<div style="font-size:11px; color:#666">Создан 18 мая · <span style="color:#323232; font-weight:700">● Открыт</span></div>
</div>
<a href="#" style="font-size:11px; color:#666; text-decoration:underline">← Все вопросы</a>
</div>
<!-- Сообщения треда -->
<div style="display:flex; flex-direction:column; gap:8px; margin-bottom:12px; max-height:200px; overflow-y:auto">
<div style="background:#E8E8E0; padding:8px 10px; border-radius:2px; max-width:88%">
<div style="font-size:10px; color:#666; margin-bottom:3px">Ты · 18 мая, 10:14</div>
<div>Привет! Хочу синхронизировать хранилище между Mac и iPhone. Пробовал iCloud, но заметки иногда конфликтуют. Есть ли рекомендованный способ?</div>
</div>
<div style="background:#F5F5F0; border:2px solid #E8F0D8; padding:8px 10px; border-radius:2px; max-width:88%; align-self:flex-end">
<div style="font-size:10px; color:#666; margin-bottom:3px">Дмитрий (куратор) · 18 мая, 11:30</div>
<div>Рекомендую Obsidian Sync — он создан специально для этого. Или как альтернатива — Working Copy + Git. Какой вариант тебе ближе?</div>
</div>
<div style="background:#E8E8E0; padding:8px 10px; border-radius:2px; max-width:88%">
<div style="font-size:10px; color:#666; margin-bottom:3px">Ты · 18 мая, 11:45</div>
<div>Лучше без платной подписки если можно. Расскажи про Working Copy?</div>
<!-- файл -->
<div style="margin-top:6px; display:flex; align-items:center; gap:5px; padding:4px 7px; background:#F5F5F0; border:1px solid #AAAAAA; border-radius:2px; font-size:11px; width:fit-content">
<span>📎</span> <span>screenshot.png</span> <span style="color:#999">· 84 KB</span>
</div>
</div>
<div style="background:#F5F5F0; border:2px solid #E8F0D8; padding:8px 10px; border-radius:2px; max-width:88%; align-self:flex-end; border-left:3px solid #323232">
<div style="font-size:10px; color:#666; margin-bottom:3px">Дмитрий (куратор) · 18 мая, 20 мин назад · <strong>🔵 новое</strong></div>
<div>Working Copy — это Git-клиент для iOS. Схема: хранилище в приватном репо GitHub, Working Copy на телефоне синкает его автоматически...</div>
</div>
</div>
<!-- Форма ответа -->
<div style="border:2px solid #AAAAAA; border-radius:2px; padding:8px; background:#F5F5F0">
<textarea style="width:100%; border:none; background:transparent; font-size:13px; resize:none; outline:none; font-family:inherit; min-height:50px" placeholder="Написать сообщение..."></textarea>
<div style="display:flex; justify-content:space-between; align-items:center; margin-top:6px; padding-top:6px; border-top:1px solid #E8E8E0">
<div style="display:flex; align-items:center; gap:6px">
<button style="padding:4px 8px; background:#F5F5F0; border:1px solid #AAAAAA; font-size:11px; border-radius:2px; cursor:pointer">📎 Прикрепить</button>
<span style="font-size:10px; color:#999">jpg, png, pdf, md · до 10 МБ</span>
</div>
<button style="padding:6px 16px; background:#323232; color:#F5F5F0; border:none; font-size:12px; font-weight:700; border-radius:2px; cursor:pointer">Отправить →</button>
</div>
</div>
</div>
</div>
</div>
@@ -0,0 +1,3 @@
<div style="display:flex;align-items:center;justify-content:center;min-height:60vh">
<p class="subtitle">Continuing in terminal...</p>
</div>
@@ -0,0 +1,3 @@
<div style="display:flex;align-items:center;justify-content:center;min-height:60vh">
<p class="subtitle">Presenting design in terminal...</p>
</div>
@@ -0,0 +1 @@
{"reason":"idle timeout","timestamp":1779178878212}
@@ -0,0 +1,10 @@
{"type":"server-started","port":49771,"host":"127.0.0.1","url_host":"localhost","url":"http://localhost:49771","screen_dir":"/Users/dementiy/Documents/Claude/lms-system/.superpowers/brainstorm/8559-1779175817/content","state_dir":"/Users/dementiy/Documents/Claude/lms-system/.superpowers/brainstorm/8559-1779175817/state"}
{"type":"screen-added","file":"/Users/dementiy/Documents/Claude/lms-system/.superpowers/brainstorm/8559-1779175817/content/entry-point.html"}
{"source":"user-event","type":"click","text":"A\n \n Только главное меню\n Пункт «Задать вопрос» в хедере / sidebar студента. Общий вопрос без привязки к уроку.\n \n Студент — sidebar\n \n 📚 Мои курсы\n 👤 Профиль\n ❓ Задать вопрос","choice":"a","id":null,"timestamp":1779175897914}
{"type":"screen-added","file":"/Users/dementiy/Documents/Claude/lms-system/.superpowers/brainstorm/8559-1779175817/content/conversation-model.html"}
{"source":"user-event","type":"click","text":"B\n \n Тред (переписка)\n Студент и админ могут писать несколько сообщений. Как поддержка-чат внутри платформы.\n \n Тред вопроса\n \n \n Ты · 14 мая\n Как настроить шаблоны?\n \n \n Дмитрий · 15 мая\n Зайди в Настройки → Шаблоны...\n \n \n Ты · 15 мая\n А какую папку лучше назвать?\n \n Написать сообщение...","choice":"b","id":null,"timestamp":1779176002499}
{"type":"screen-added","file":"/Users/dementiy/Documents/Claude/lms-system/.superpowers/brainstorm/8559-1779175817/content/waiting-1.html"}
{"type":"screen-added","file":"/Users/dementiy/Documents/Claude/lms-system/.superpowers/brainstorm/8559-1779175817/content/admin-views.html"}
{"type":"screen-added","file":"/Users/dementiy/Documents/Claude/lms-system/.superpowers/brainstorm/8559-1779175817/content/waiting-2.html"}
{"type":"screen-added","file":"/Users/dementiy/Documents/Claude/lms-system/.superpowers/brainstorm/8559-1779175817/content/student-questions.html"}
{"type":"server-stopped","reason":"idle timeout"}
@@ -0,0 +1 @@
8568
+3
View File
@@ -9,6 +9,9 @@ FROM node:20-alpine AS builder
WORKDIR /app WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules COPY --from=deps /app/node_modules ./node_modules
COPY . . COPY . .
# NEXT_PUBLIC_* vars are inlined at build time
ARG NEXT_PUBLIC_TURNSTILE_SITE_KEY
ENV NEXT_PUBLIC_TURNSTILE_SITE_KEY=$NEXT_PUBLIC_TURNSTILE_SITE_KEY
# Generate Prisma client before build # Generate Prisma client before build
RUN npx prisma generate RUN npx prisma generate
RUN npm run build RUN npm run build
@@ -0,0 +1,451 @@
# LMS Staging Environment Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Развернуть полноценный staging-стенд LMS на `staging.school.second-brain.ru` — изолированный от prod, с автоматическим применением миграций и отключёнными email-уведомлениями.
**Architecture:** Hetzner VPS (178.104.27.196, 16 GB RAM), отдельный Docker Compose стек в `/root/digital-household/lms-staging/` с собственным postgres-контейнером. Caddy на том же сервере роутит `staging.school.second-brain.ru → localhost:3011`. Сборочный репо — `/root/lms-staging-build/`, тег образа — `lms-staging-app:latest`. Деплой в staging производится отдельным скриптом `deploy-staging.sh` независимо от prod.
**Tech Stack:** Docker Compose, Next.js 16 (App Router), PostgreSQL 16, Caddy, Gitea (git.second-brain.ru/admins/lms-sb)
---
## Файловая структура
```
Hetzner VPS (root@178.104.27.196):
├── /root/lms-staging-build/ ← git clone (сборочная директория)
│ └── [полный репо lms-sb]
├── /root/digital-household/lms-staging/
│ ├── docker-compose.yml ← создаём (app + db)
│ └── .env ← создаём (staging-специфичный)
└── /root/digital-household/caddy-proxy/
└── Caddyfile ← добавляем блок staging
Mac:
└── ~/Documents/Claude/scripts/deploy-staging.sh ← создаём
```
---
## Task 1: Клонировать репо на Hetzner
**Files:**
- Создаём: `/root/lms-staging-build/` на сервере
- [ ] **Шаг 1.1: SSH на Hetzner и клонировать репо**
Нужен токен Gitea. Он хранится в уже существующем git remote на сервере. Достанем его:
```bash
ssh root@178.104.27.196 "git -C /root/digital-household/lms-sb remote get-url origin 2>/dev/null || echo 'no-remote'"
```
Если remote есть — берём URL из него. Если нет — токен в `~/.config/secrets/` на Mac (найти файл с `GITEA_TOKEN` или `git.second-brain.ru`).
- [ ] **Шаг 1.2: Клонировать**
```bash
GITEA_URL=$(ssh root@178.104.27.196 "git -C /root/digital-household/lms-sb remote get-url origin 2>/dev/null")
# Пример: https://admins:TOKEN@git.second-brain.ru/admins/lms-sb.git
ssh root@178.104.27.196 "git clone ${GITEA_URL} /root/lms-staging-build"
```
- [ ] **Шаг 1.3: Проверить**
```bash
ssh root@178.104.27.196 "ls /root/lms-staging-build/src && git -C /root/lms-staging-build log --oneline -3"
```
Ожидаем: список файлов и последние 3 коммита.
---
## Task 2: Создать staging docker-compose.yml
**Files:**
- Создаём: `/root/digital-household/lms-staging/docker-compose.yml`
- [ ] **Шаг 2.1: Создать директорию**
```bash
ssh root@178.104.27.196 "mkdir -p /root/digital-household/lms-staging"
```
- [ ] **Шаг 2.2: Записать docker-compose.yml**
```bash
ssh root@178.104.27.196 "cat > /root/digital-household/lms-staging/docker-compose.yml" << 'COMPOSE'
services:
app:
image: lms-staging-app:latest
restart: unless-stopped
ports:
- "3011:3000"
env_file: .env
depends_on:
db:
condition: service_healthy
db:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_USER: lms_staging_user
POSTGRES_PASSWORD: "${DB_PASSWORD}"
POSTGRES_DB: lms_staging_db
volumes:
- staging_postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U lms_staging_user -d lms_staging_db"]
interval: 5s
timeout: 5s
retries: 10
volumes:
staging_postgres_data:
COMPOSE
```
- [ ] **Шаг 2.3: Проверить**
```bash
ssh root@178.104.27.196 "cat /root/digital-household/lms-staging/docker-compose.yml"
```
Ожидаем: полный YAML без артефактов heredoc.
---
## Task 3: Залить staging .env на сервер
**Files:**
- Создаём: `/root/digital-household/lms-staging/.env`
Все креды уже сгенерированы и хранятся в `~/.config/secrets/lms-staging.env` на Mac.
- [ ] **Шаг 3.1: Скопировать .env на сервер**
```bash
scp ~/.config/secrets/lms-staging.env root@178.104.27.196:/root/digital-household/lms-staging/.env
```
- [ ] **Шаг 3.2: Установить права**
```bash
ssh root@178.104.27.196 "chmod 600 /root/digital-household/lms-staging/.env"
```
- [ ] **Шаг 3.3: Проверить**
```bash
ssh root@178.104.27.196 "grep -E '^BETTER_AUTH_URL|^RESEND_API_KEY|^DB_PASSWORD' /root/digital-household/lms-staging/.env"
```
Ожидаем:
```
BETTER_AUTH_URL=https://staging.school.second-brain.ru
RESEND_API_KEY=
DB_PASSWORD=38002343e67efd057559d8f073d45892
```
---
## Task 4: Собрать Docker-образ и запустить staging
**Files:**
- Используем `/root/lms-staging-build/` для сборки
- [ ] **Шаг 4.1: Собрать образ**
```bash
ssh root@178.104.27.196 "cd /root/lms-staging-build && docker build -t lms-staging-app:latest . 2>&1 | tail -5"
```
Ожидаем: `Successfully built ...` или `naming to docker.io/library/lms-staging-app:latest done`.
Время: ~2–4 минуты.
- [ ] **Шаг 4.2: Запустить контейнеры**
```bash
ssh root@178.104.27.196 "cd /root/digital-household/lms-staging && docker compose up -d"
```
Ожидаем: `Container lms-staging-db-1 Started`, `Container lms-staging-app-1 Started`.
- [ ] **Шаг 4.3: Проверить логи (через 10 сек)**
```bash
ssh root@178.104.27.196 "sleep 10 && docker logs lms-staging-app-1 --tail 20"
```
Ожидаем в логах:
- `Running database migrations...`
- `No pending migrations to apply.` (или список применённых)
- `Starting Next.js...`
- `✓ Ready in 0ms`
Если вместо этого ошибка `DATABASE_URL` или `connection refused` — проверить `.env`: `docker exec lms-staging-app-1 env | grep DATABASE`.
---
## Task 5: Настроить Caddy
**Files:**
- Изменяем: `/root/digital-household/caddy-proxy/Caddyfile`
- [ ] **Шаг 5.1: Посмотреть текущий конец Caddyfile**
```bash
ssh root@178.104.27.196 "tail -10 /root/digital-household/caddy-proxy/Caddyfile"
```
- [ ] **Шаг 5.2: Добавить блок для staging**
```bash
ssh root@178.104.27.196 "cat >> /root/digital-household/caddy-proxy/Caddyfile" << 'CADDY'
staging.school.second-brain.ru {
reverse_proxy http://localhost:3011
}
CADDY
```
- [ ] **Шаг 5.3: Перезагрузить Caddy**
```bash
ssh root@178.104.27.196 "docker exec caddy-proxy caddy reload --config /etc/caddy/Caddyfile 2>&1"
```
Ожидаем: пустой вывод (успех) или `Successfully loaded new configuration`.
Если ошибка синтаксиса — проверить: `docker exec caddy-proxy caddy validate --config /etc/caddy/Caddyfile`.
---
## Task 6: Добавить DNS-запись
DNS для `*.school.second-brain.ru` и `school.second-brain.ru` нужно проверить — где управляется зона.
- [ ] **Шаг 6.1: Проверить текущий DNS**
```bash
dig +short staging.school.second-brain.ru
dig +short school.second-brain.ru
```
Если `staging.school.second-brain.ru` не резолвится — нужно добавить A-запись.
- [ ] **Шаг 6.2: Добавить A-запись**
В панели DNS (Hetzner DNS Console или CloudFlare — где управляется зона `second-brain.ru`):
```
Тип: A
Имя: staging.school
Значение: 178.104.27.196
TTL: 300
```
- [ ] **Шаг 6.3: Дождаться распространения**
```bash
# Через 1-2 минуты:
dig +short staging.school.second-brain.ru
```
Ожидаем: `178.104.27.196`
---
## Task 7: Проверить работу staging end-to-end
- [ ] **Шаг 7.1: HTTP проверка**
```bash
curl -s -o /dev/null -w "%{http_code}" https://staging.school.second-brain.ru/login
```
Ожидаем: `200`
- [ ] **Шаг 7.2: Войти под тестовым аккаунтом**
Открыть `https://staging.school.second-brain.ru/login` в браузере.
БД пустая, но seed создаёт admin-аккаунт. Запустить seed:
```bash
ssh root@178.104.27.196 "cd /root/lms-staging-build && docker compose -f /root/digital-household/lms-staging/docker-compose.yml exec app npx prisma db seed 2>&1 | tail -5"
```
После seed входить: `admin@second-brain.ru` / `Password123!`
- [ ] **Шаг 7.3: Проверить что email не уходит**
В staging при регистрации `/api/auth/sign-up` не должно быть ошибок Resend (только `RESEND_API_KEY` пустой — письмо тихо не отправляется, регистрация всё равно работает).
Убедиться в логах:
```bash
ssh root@178.104.27.196 "docker logs lms-staging-app-1 --since 5m 2>&1 | grep -i 'resend\|email\|error' | head -10"
```
---
## Task 8: Скрипт deploy-to-staging и документация
**Files:**
- Создаём: `~/Documents/Claude/scripts/deploy-staging.sh`
- Создаём: `SBT/02-Стандарты/Процессы/lms-staging-deploy.md`
- [ ] **Шаг 8.1: Написать скрипт deploy-staging.sh**
```bash
cat > ~/Documents/Claude/scripts/deploy-staging.sh << 'SCRIPT'
#!/usr/bin/env bash
# Deploy LMS to staging (staging.school.second-brain.ru)
# Usage: bash deploy-staging.sh
set -euo pipefail
STAGING_SERVER="root@178.104.27.196"
BUILD_DIR="/root/lms-staging-build"
COMPOSE_DIR="/root/digital-household/lms-staging"
LOG_LINES=15
echo "=== LMS Staging Deploy ==="
echo "→ Pulling latest code..."
ssh "$STAGING_SERVER" "cd ${BUILD_DIR} && git pull 2>&1 | tail -5"
echo "→ Building image..."
ssh "$STAGING_SERVER" "cd ${BUILD_DIR} && docker build -t lms-staging-app:latest . 2>&1 | tail -5"
echo "→ Restarting app..."
ssh "$STAGING_SERVER" "cd ${COMPOSE_DIR} && docker compose up -d app"
echo "→ Waiting 10s for startup..."
sleep 10
echo "→ Logs:"
ssh "$STAGING_SERVER" "docker logs lms-staging-app-1 --tail ${LOG_LINES} 2>&1"
echo "→ Health check..."
CODE=$(curl -s -o /dev/null -w "%{http_code}" https://staging.school.second-brain.ru/login)
if [ "$CODE" = "200" ]; then
echo "✅ Staging OK — https://staging.school.second-brain.ru (HTTP $CODE)"
else
echo "❌ Staging returned HTTP $CODE"
exit 1
fi
SCRIPT
chmod +x ~/Documents/Claude/scripts/deploy-staging.sh
```
- [ ] **Шаг 8.2: Тестовый запуск скрипта**
```bash
bash ~/Documents/Claude/scripts/deploy-staging.sh
```
Ожидаем в конце: `✅ Staging OK — https://staging.school.second-brain.ru (HTTP 200)`
- [ ] **Шаг 8.3: Создать SBT-заметку**
Создать файл `SBT/02-Стандарты/Процессы/lms-staging-deploy.md` со следующим содержимым:
```markdown
---
type: process
title: "LMS — Деплой в staging"
status: active
created: 20260525
updated: 20260525
tags: [lms, staging, deploy, docker]
related: ["[[Процессы/lms-deploy]]", "[[Сервисы/hoster-kz]]", "[[Сервисы/vps-hetzner]]"]
---
# Процесс: Деплой LMS в staging
## Когда применяется
Перед выкаткой любых изменений в prod — сначала деплоим в staging и проверяем.
Также: тестирование миграций БД, проверка новых фич, отладка.
## Ключевые факты
| Что | Где |
|---|---|
| URL | https://staging.school.second-brain.ru |
| Сервер | Hetzner Antigravity-1 (178.104.27.196) |
| Compose | `/root/digital-household/lms-staging/` |
| Build dir | `/root/lms-staging-build/` |
| Порт | 3011 |
| БД | `lms_staging_db` (отдельный контейнер) |
| Email | Отключён (RESEND_API_KEY пустой) |
| S3 | Тот же бакет что и prod |
## Деплой одной командой (с Mac)
```bash
bash ~/Documents/Claude/scripts/deploy-staging.sh
```
## Ручные шаги (если нужно)
```bash
# На сервере
cd /root/lms-staging-build && git pull
docker build -t lms-staging-app:latest .
cd /root/digital-household/lms-staging && docker compose up -d app
docker logs lms-staging-app-1 --tail 20
```
## Откат
```bash
ssh root@178.104.27.196 "cd /root/digital-household/lms-staging && docker compose down"
```
## Восстановить prod-данные в staging (для отладки)
```bash
# 1. Взять свежий дамп с 3TB или Storage Box
# 2. Залить в staging-базу
DUMP="/Volumes/3TB/Second Brain Production/LMS Backups/lms-db-YYYYMMDD-HHMM.sql.gz"
scp "$DUMP" root@178.104.27.196:/tmp/staging-restore.sql.gz
ssh root@178.104.27.196 \
"zcat /tmp/staging-restore.sql.gz | docker exec -i lms-staging-db-1 psql -U lms_staging_user lms_staging_db"
```
## Связанные процессы
- [[Процессы/lms-deploy]] — деплой в prod (после проверки на staging)
- [[Процессы/lms-disaster-recovery]]
```
- [ ] **Шаг 8.4: Коммит скрипта**
```bash
cd ~/Documents/Claude/lms-system
git add docs/
git commit -m "Add LMS staging environment plan and deploy script"
git push origin HEAD
```
---
## Чек-лист финальной проверки
- [ ] `https://staging.school.second-brain.ru/login` → 200
- [ ] Войти под тестовым аккаунтом
- [ ] Курс открывается
- [ ] Email НЕ уходит при регистрации (проверить логи)
- [ ] `bash deploy-staging.sh` завершается с `✅ Staging OK`
- [ ] SBT-заметка создана
---
## Ожидаемое время
~30–40 минут (основное время — сборка Docker-образа ~3–5 мин).
+1
View File
@@ -0,0 +1 @@
{"0": "Admin Categories & UI Library", "1": "Auth Flow & App Settings", "2": "Markdown→TipTap Import", "3": "Email Notifications & Q&A API", "4": "Student Lesson Player", "5": "Auth/Session & Student Profile", "6": "Lesson Editor & Quiz Tools", "7": "Admin User Detail (Balance/Contact)", "8": "Next.js Config", "9": "Course Tree & Module Sorting", "10": "CSV Import/Export", "11": "Curator Homework Review", "12": "Components Manifest", "13": "Prisma Client & Dashboards", "14": "Admin Users List & Enroll", "15": "TSConfig", "16": "S3 Upload Routes", "17": "Module Page & Lesson Sorting", "18": "Cross-cutting Course Actions", "19": "Create-User Form", "20": "Load Testing", "21": "Admin Comments Moderation", "22": "Admin Questions Split View", "23": "Bridge: Shared Libs (auth/prisma/email)", "24": "Module Actions Standalone", "25": "Student Course Sidebar Layout", "26": "Question Thread UI", "27": "Admin/Curator Dashboards", "28": "Homework Filters", "29": "Student New Question Page", "30": "Prisma Seed", "31": "Admin Homework Actions", "32": "Middleware", "33": "Email→Homework→Questions Bridge", "34": "Tech Docs & Prisma Schema", "35": "Lesson Actions Lib", "36": "Student Comment Actions", "37": "Lesson Actions + Prisma Bridge", "38": "Project Docs (CLAUDE/ROADMAP)", "39": "Homework Editor↔Actions Pair", "40": "File-format Badge & Files Manager", "41": "Auth↔Middleware Pair", "42": "ESLint Config", "43": "PostCSS Config", "44": "Lesson Editor↔md-to-tiptap", "45": "Sortable Lessons↔Module Actions", "46": "Quiz Editor↔Quiz Actions", "47": "Backup Script", "48": "Verify Email Page", "49": "Maintenance Page", "50": "Sonner Toast", "51": "User Enrollment Pair", "52": "Community 52", "53": "Community 53", "54": "Community 54", "55": "Community 55", "56": "Community 56", "57": "Community 57", "58": "Community 58", "59": "Community 59", "60": "Community 60", "61": "Community 61", "62": "Community 62", "63": "Community 63", "64": "Community 64", "65": "Community 65", "66": "Community 66", "67": "Community 67", "68": "Community 68", "69": "Community 69", "70": "Community 70", "71": "Community 71", "72": "Community 72", "73": "Community 73", "74": "Community 74", "75": "Community 75", "76": "Community 76", "77": "Community 77", "78": "Community 78"}
+1
View File
@@ -0,0 +1 @@
/Users/dementiy/.local/share/uv/tools/graphifyy/bin/python3
+1
View File
@@ -0,0 +1 @@
/Users/dementiy/Documents/Claude/lms-system
+253
View File
@@ -0,0 +1,253 @@
# Graph Report - /Users/dementiy/Documents/Claude/lms-system (2026-05-20)
## Corpus Check
- 189 files · ~66,515 words
- Verdict: corpus is large enough that graph structure adds value.
## Summary
- 747 nodes · 1213 edges · 79 communities (37 shown, 42 thin omitted)
- Extraction: 100% EXTRACTED · 0% INFERRED · 0% AMBIGUOUS · INFERRED: 4 edges (avg confidence: 0.85)
- Token cost: 193,752 input · 7,975 output
## Community Hubs (Navigation)
- [[_COMMUNITY_Admin Categories & UI Library|Admin Categories & UI Library]]
- [[_COMMUNITY_Auth Flow & App Settings|Auth Flow & App Settings]]
- [[_COMMUNITY_Markdown→TipTap Import|Markdown→TipTap Import]]
- [[_COMMUNITY_Email Notifications & Q&A API|Email Notifications & Q&A API]]
- [[_COMMUNITY_Student Lesson Player|Student Lesson Player]]
- [[_COMMUNITY_AuthSession & Student Profile|Auth/Session & Student Profile]]
- [[_COMMUNITY_Lesson Editor & Quiz Tools|Lesson Editor & Quiz Tools]]
- [[_COMMUNITY_Admin User Detail (BalanceContact)|Admin User Detail (Balance/Contact)]]
- [[_COMMUNITY_Next.js Config|Next.js Config]]
- [[_COMMUNITY_Course Tree & Module Sorting|Course Tree & Module Sorting]]
- [[_COMMUNITY_CSV ImportExport|CSV Import/Export]]
- [[_COMMUNITY_Curator Homework Review|Curator Homework Review]]
- [[_COMMUNITY_Components Manifest|Components Manifest]]
- [[_COMMUNITY_Prisma Client & Dashboards|Prisma Client & Dashboards]]
- [[_COMMUNITY_Admin Users List & Enroll|Admin Users List & Enroll]]
- [[_COMMUNITY_TSConfig|TSConfig]]
- [[_COMMUNITY_S3 Upload Routes|S3 Upload Routes]]
- [[_COMMUNITY_Module Page & Lesson Sorting|Module Page & Lesson Sorting]]
- [[_COMMUNITY_Cross-cutting Course Actions|Cross-cutting Course Actions]]
- [[_COMMUNITY_Create-User Form|Create-User Form]]
- [[_COMMUNITY_Load Testing|Load Testing]]
- [[_COMMUNITY_Admin Comments Moderation|Admin Comments Moderation]]
- [[_COMMUNITY_Admin Questions Split View|Admin Questions Split View]]
- [[_COMMUNITY_Bridge Shared Libs (authprismaemail)|Bridge: Shared Libs (auth/prisma/email)]]
- [[_COMMUNITY_Module Actions Standalone|Module Actions Standalone]]
- [[_COMMUNITY_Student Course Sidebar Layout|Student Course Sidebar Layout]]
- [[_COMMUNITY_Question Thread UI|Question Thread UI]]
- [[_COMMUNITY_AdminCurator Dashboards|Admin/Curator Dashboards]]
- [[_COMMUNITY_Homework Filters|Homework Filters]]
- [[_COMMUNITY_Student New Question Page|Student New Question Page]]
- [[_COMMUNITY_Prisma Seed|Prisma Seed]]
- [[_COMMUNITY_Admin Homework Actions|Admin Homework Actions]]
- [[_COMMUNITY_Middleware|Middleware]]
- [[_COMMUNITY_Email→Homework→Questions Bridge|Email→Homework→Questions Bridge]]
- [[_COMMUNITY_Tech Docs & Prisma Schema|Tech Docs & Prisma Schema]]
- [[_COMMUNITY_Lesson Actions Lib|Lesson Actions Lib]]
- [[_COMMUNITY_Lesson Actions + Prisma Bridge|Lesson Actions + Prisma Bridge]]
- [[_COMMUNITY_Project Docs (CLAUDEROADMAP)|Project Docs (CLAUDE/ROADMAP)]]
- [[_COMMUNITY_Homework Editor↔Actions Pair|Homework Editor↔Actions Pair]]
- [[_COMMUNITY_File-format Badge & Files Manager|File-format Badge & Files Manager]]
- [[_COMMUNITY_Auth↔Middleware Pair|Auth↔Middleware Pair]]
- [[_COMMUNITY_ESLint Config|ESLint Config]]
- [[_COMMUNITY_PostCSS Config|PostCSS Config]]
- [[_COMMUNITY_Lesson Editor↔md-to-tiptap|Lesson Editor↔md-to-tiptap]]
- [[_COMMUNITY_Sortable Lessons↔Module Actions|Sortable Lessons↔Module Actions]]
- [[_COMMUNITY_Quiz Editor↔Quiz Actions|Quiz Editor↔Quiz Actions]]
- [[_COMMUNITY_User Enrollment Pair|User Enrollment Pair]]
- [[_COMMUNITY_Community 54|Community 54]]
- [[_COMMUNITY_Community 55|Community 55]]
- [[_COMMUNITY_Community 56|Community 56]]
- [[_COMMUNITY_Community 57|Community 57]]
- [[_COMMUNITY_Community 58|Community 58]]
- [[_COMMUNITY_Community 59|Community 59]]
- [[_COMMUNITY_Community 60|Community 60]]
- [[_COMMUNITY_Community 61|Community 61]]
- [[_COMMUNITY_Community 62|Community 62]]
- [[_COMMUNITY_Community 63|Community 63]]
- [[_COMMUNITY_Community 64|Community 64]]
- [[_COMMUNITY_Community 65|Community 65]]
- [[_COMMUNITY_Community 66|Community 66]]
- [[_COMMUNITY_Community 67|Community 67]]
- [[_COMMUNITY_Community 68|Community 68]]
- [[_COMMUNITY_Community 69|Community 69]]
- [[_COMMUNITY_Community 70|Community 70]]
- [[_COMMUNITY_Community 71|Community 71]]
- [[_COMMUNITY_Community 72|Community 72]]
- [[_COMMUNITY_Community 73|Community 73]]
- [[_COMMUNITY_Community 74|Community 74]]
- [[_COMMUNITY_Community 75|Community 75]]
- [[_COMMUNITY_Community 76|Community 76]]
- [[_COMMUNITY_Community 77|Community 77]]
- [[_COMMUNITY_Community 78|Community 78]]
## God Nodes (most connected - your core abstractions)
1. `auth` - 55 edges
2. `cn()` - 39 edges
3. `compilerOptions` - 16 edges
4. `getSetting()` - 15 edges
5. `uploadFile()` - 14 edges
6. `getSchoolName()` - 13 edges
7. `Prisma Client` - 13 edges
8. `getResend()` - 12 edges
9. `base()` - 12 edges
10. `btn()` - 12 edges
## Surprising Connections (you probably didn't know these)
- `cn()` --calls--> `clsx` [INFERRED]
src/lib/utils.ts → package.json
- `mdToTiptap()` --calls--> `unified` [INFERRED]
src/lib/md-to-tiptap.ts → package.json
- `Claude Project Rules` --references--> `Project Roadmap` [EXTRACTED]
CLAUDE.md → ROADMAP.md
- `Technical Documentation` --references--> `Prisma Schema` [EXTRACTED]
TECHNICAL.md → prisma/schema.prisma
- `generateMetadata()` --calls--> `getSettings` [EXTRACTED]
src/app/layout.tsx → src/lib/settings.ts
## Communities (79 total, 42 thin omitted)
### Community 0 - "Admin Categories & UI Library"
Cohesion: 0.06
Nodes (49): CategoryRow(), Props, Category, Course, CreateCourseDialog(), createCategory(), deleteCategory(), requireAdmin() (+41 more)
### Community 1 - "Auth Flow & App Settings"
Cohesion: 0.07
Nodes (29): AdminNav(), links, AdminShell(), focusHandlers, inputStyle, SettingsForm(), StopImpersonateBanner(), firaMono (+21 more)
### Community 2 - "Markdown→TipTap Import"
Cohesion: 0.05
Nodes (41): POST(), convertBlock(), convertInline(), Mark, MdastNode, mdToTiptap(), TipTapNode, dependencies (+33 more)
### Community 3 - "Email Notifications & Q&A API"
Cohesion: 0.15
Nodes (30): createModule(), deleteModule(), grantAccess(), reorderModules(), requireAdmin(), revokeAccess(), updateModule(), HomeworkFile (+22 more)
### Community 4 - "Student Lesson Player"
Cohesion: 0.08
Nodes (24): addComment(), deleteComment(), HomeworkFile, submitHomework(), submitQuizAttempt(), toggleLessonProgress(), parseNotificationEmails(), KinescopePlayer() (+16 more)
### Community 5 - "Auth/Session & Student Profile"
Cohesion: 0.09
Nodes (6): { GET, POST }, auth, Session, User, metadata, POST()
### Community 6 - "Lesson Editor & Quiz Tools"
Cohesion: 0.09
Nodes (22): deleteHomework(), requireAdmin(), saveHomework(), deleteQuiz(), requireAdmin(), saveQuiz(), HomeworkEditor(), Props (+14 more)
### Community 7 - "Admin User Detail (Balance/Contact)"
Cohesion: 0.10
Nodes (25): bulkGrantAccess(), requireAdmin(), revokeUserAccess(), focusHandlers, formatAmount(), inputStyle, Props, Transaction (+17 more)
### Community 8 - "Next.js Config"
Cohesion: 0.07
Nodes (26): nextConfig, devDependencies, dotenv, eslint, eslint-config-next, prisma, tailwindcss, @tailwindcss/postcss (+18 more)
### Community 9 - "Course Tree & Module Sorting"
Cohesion: 0.13
Nodes (19): createModule(), deleteModule(), grantAccess(), reorderModules(), requireAdmin(), revokeAccess(), updateModule(), CourseEditForm() (+11 more)
### Community 10 - "CSV Import/Export"
Cohesion: 0.12
Nodes (18): Course, CsvExporter(), focusHandlers, inputStyle, Course, CsvImporter(), focusHandlers, inputStyle (+10 more)
### Community 11 - "Curator Homework Review"
Cohesion: 0.12
Nodes (14): AudioRecorder(), AudioRecorderProps, ContentViewer(), asBool(), deleteSubmission(), requireCurator(), setReviewing(), submitFeedback() (+6 more)
### Community 12 - "Components Manifest"
Cohesion: 0.09
Nodes (21): aliases, components, hooks, lib, ui, utils, iconLibrary, menuAccent (+13 more)
### Community 13 - "Prisma Client & Dashboards"
Cohesion: 0.10
Nodes (7): Props, requireAdmin(), saveLesson(), globalForPrisma, Props, metadata, Props
### Community 14 - "Admin Users List & Enroll"
Cohesion: 0.12
Nodes (14): Course, Props, QuickEnrollButton(), inputStyle, UsersSearch(), Enrollment, roleLabel, roleVariant (+6 more)
### Community 15 - "TSConfig"
Cohesion: 0.10
Nodes (19): compilerOptions, allowJs, esModuleInterop, incremental, isolatedModules, jsx, lib, module (+11 more)
### Community 16 - "S3 Upload Routes"
Cohesion: 0.22
Nodes (12): POST(), POST(), DELETE(), PATCH(), POST(), requireAdmin(), deleteFile(), getPublicUrl() (+4 more)
### Community 17 - "Module Page & Lesson Sorting"
Cohesion: 0.23
Nodes (11): createLesson(), deleteLesson(), moveLessonToModule(), reorderLessons(), requireAdmin(), toggleLessonPublished(), updateLesson(), Lesson (+3 more)
### Community 18 - "Cross-cutting Course Actions"
Cohesion: 0.12
Nodes (16): Course Detail Page, Create Course Action, Admin Dashboard, AdminLayout(), Create Lesson Action, Create Module Action, User Detail Page, Create User Action (+8 more)
### Community 19 - "Create-User Form"
Cohesion: 0.18
Nodes (6): CreateUserForm(), focusHandlers, inputStyle, ROLES, metadata, createUser()
### Community 20 - "Load Testing"
Cohesion: 0.20
Nodes (9): BROWSER_HEADERS, courseRes, dashRes, jar, lessonRes, LESSONS, loginRes, options (+1 more)
### Community 21 - "Admin Comments Moderation"
Cohesion: 0.24
Nodes (6): Comment, CommentsTable(), inputStyle, adminDeleteComment(), metadata, Props
### Community 22 - "Admin Questions Split View"
Cohesion: 0.22
Nodes (5): FileAttachment, Message, QuestionDetail, QuestionSplitView(), QuestionSummary
### Community 23 - "Bridge: Shared Libs (auth/prisma/email)"
Cohesion: 0.22
Nodes (9): AudioRecorder, Better Auth, grantAccess, Email Senders, EnrollmentManager, HomeworkSection, Prisma Client, getSettings (+1 more)
### Community 24 - "Module Actions Standalone"
Cohesion: 0.46
Nodes (7): createLesson(), deleteLesson(), moveLessonToModule(), reorderLessons(), requireAdmin(), toggleLessonPublished(), updateLesson()
### Community 25 - "Student Course Sidebar Layout"
Cohesion: 0.29
Nodes (5): Props, Course, CourseSidebar(), Lesson, Module
### Community 26 - "Question Thread UI"
Cohesion: 0.29
Nodes (4): FileAttachment, Message, QuestionThread(), QuestionThreadProps
### Community 31 - "Admin Homework Actions"
Cohesion: 0.83
Nodes (3): deleteHomework(), requireAdmin(), saveHomework()
### Community 33 - "Email→Homework→Questions Bridge"
Cohesion: 0.67
Nodes (3): Questions API Route, Email Helpers (Resend), Homework Submission Actions
### Community 37 - "Lesson Actions + Prisma Bridge"
Cohesion: 0.67
Nodes (3): Prisma Client Singleton, Lesson Comment Actions, Lesson Progress Actions
## Knowledge Gaps
- **278 isolated node(s):** `config`, `LESSONS`, `TEST_USER`, `BROWSER_HEADERS`, `options` (+273 more)
These have ≤1 connection - possible missing edges or undocumented components.
- **42 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
## Suggested Questions
_Questions this graph is uniquely positioned to answer:_
- **Why does `dependencies` connect `Markdown→TipTap Import` to `Next.js Config`, `Cross-cutting Course Actions`?**
_High betweenness centrality (0.128) - this node is a cross-community bridge._
- **Why does `auth` connect `Auth/Session & Student Profile` to `Admin Categories & UI Library`, `Auth Flow & App Settings`, `Markdown→TipTap Import`, `Email Notifications & Q&A API`, `Student Lesson Player`, `Lesson Editor & Quiz Tools`, `Admin User Detail (Balance/Contact)`, `Course Tree & Module Sorting`, `CSV Import/Export`, `Curator Homework Review`, `Prisma Client & Dashboards`, `Admin Users List & Enroll`, `S3 Upload Routes`, `Module Page & Lesson Sorting`, `Admin Comments Moderation`, `Admin Questions Split View`, `Module Actions Standalone`, `Student Course Sidebar Layout`, `Admin/Curator Dashboards`, `Admin Homework Actions`, `Lesson Actions Lib`, `Student Comment Actions`?**
_High betweenness centrality (0.121) - this node is a cross-community bridge._
- **What connects `config`, `LESSONS`, `TEST_USER` to the rest of the system?**
_278 weakly-connected nodes found - possible documentation gaps or missing edges._
- **Should `Admin Categories & UI Library` be split into smaller, more focused modules?**
_Cohesion score 0.06377151799687011 - nodes in this community are weakly interconnected._
- **Should `Auth Flow & App Settings` be split into smaller, more focused modules?**
_Cohesion score 0.06787330316742081 - nodes in this community are weakly interconnected._
- **Should `Markdown→TipTap Import` be split into smaller, more focused modules?**
_Cohesion score 0.05094130675526024 - nodes in this community are weakly interconnected._
- **Should `Student Lesson Player` be split into smaller, more focused modules?**
_Cohesion score 0.08235294117647059 - nodes in this community are weakly interconnected._
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_components_layout_logout_button_tsx", "label": "logout-button.tsx", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/layout/logout-button.tsx", "source_location": "L1"}, {"id": "layout_logout_button_logoutbutton", "label": "LogoutButton()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/layout/logout-button.tsx", "source_location": "L6"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_components_layout_logout_button_tsx", "target": "navigation", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/layout/logout-button.tsx", "source_location": "L3", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_layout_logout_button_tsx", "target": "users_dementiy_documents_claude_lms_system_src_lib_auth_client_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/layout/logout-button.tsx", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_layout_logout_button_tsx", "target": "lib_auth_client_signout", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/layout/logout-button.tsx", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_layout_logout_button_tsx", "target": "layout_logout_button_logoutbutton", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/layout/logout-button.tsx", "source_location": "L6", "weight": 1.0}], "raw_calls": [{"caller_nid": "layout_logout_button_logoutbutton", "callee": "useRouter", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/layout/logout-button.tsx", "source_location": "L7"}]}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_prisma_config_ts", "label": "prisma.config.ts", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/prisma.config.ts", "source_location": "L1"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_prisma_config_ts", "target": "config", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/prisma.config.ts", "source_location": "L3", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_prisma_config_ts", "target": "config", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/prisma.config.ts", "source_location": "L4", "weight": 1.0}], "raw_calls": []}
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_app_admin_import_export_page_tsx", "label": "page.tsx", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/import-export/page.tsx", "source_location": "L1"}, {"id": "import_export_page_metadata", "label": "metadata", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/import-export/page.tsx", "source_location": "L5"}, {"id": "import_export_page_importexportpage", "label": "ImportExportPage()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/import-export/page.tsx", "source_location": "L7"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_app_admin_import_export_page_tsx", "target": "users_dementiy_documents_claude_lms_system_src_lib_prisma_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/import-export/page.tsx", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_import_export_page_tsx", "target": "lib_prisma_prisma", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/import-export/page.tsx", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_import_export_page_tsx", "target": "users_dementiy_documents_claude_lms_system_src_components_admin_csv_importer_tsx", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/import-export/page.tsx", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_import_export_page_tsx", "target": "admin_csv_importer_csvimporter", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/import-export/page.tsx", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_import_export_page_tsx", "target": "users_dementiy_documents_claude_lms_system_src_components_admin_csv_exporter_tsx", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/import-export/page.tsx", "source_location": "L3", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_import_export_page_tsx", "target": "admin_csv_exporter_csvexporter", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/import-export/page.tsx", "source_location": "L3", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_import_export_page_tsx", "target": "import_export_page_metadata", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/import-export/page.tsx", "source_location": "L5", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_import_export_page_tsx", "target": "import_export_page_importexportpage", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/import-export/page.tsx", "source_location": "L7", "weight": 1.0}], "raw_calls": [{"caller_nid": "import_export_page_importexportpage", "callee": "findMany", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/import-export/page.tsx", "source_location": "L8"}]}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_app_admin_comments_actions_ts", "label": "actions.ts", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/comments/actions.ts", "source_location": "L1"}, {"id": "comments_actions_admindeletecomment", "label": "adminDeleteComment()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/comments/actions.ts", "source_location": "L8"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_app_admin_comments_actions_ts", "target": "headers", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/comments/actions.ts", "source_location": "L3", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_comments_actions_ts", "target": "users_dementiy_documents_claude_lms_system_src_lib_auth_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/comments/actions.ts", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_comments_actions_ts", "target": "lib_auth_auth", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/comments/actions.ts", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_comments_actions_ts", "target": "users_dementiy_documents_claude_lms_system_src_lib_prisma_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/comments/actions.ts", "source_location": "L5", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_comments_actions_ts", "target": "lib_prisma_prisma", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/comments/actions.ts", "source_location": "L5", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_comments_actions_ts", "target": "cache", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/comments/actions.ts", "source_location": "L6", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_comments_actions_ts", "target": "comments_actions_admindeletecomment", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/comments/actions.ts", "source_location": "L8", "weight": 1.0}], "raw_calls": [{"caller_nid": "comments_actions_admindeletecomment", "callee": "getSession", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/comments/actions.ts", "source_location": "L9"}, {"caller_nid": "comments_actions_admindeletecomment", "callee": "headers", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/comments/actions.ts", "source_location": "L9"}, {"caller_nid": "comments_actions_admindeletecomment", "callee": "update", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/comments/actions.ts", "source_location": "L12"}, {"caller_nid": "comments_actions_admindeletecomment", "callee": "revalidatePath", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/comments/actions.ts", "source_location": "L17"}]}
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_components_admin_homework_filters_tsx", "label": "homework-filters.tsx", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/homework-filters.tsx", "source_location": "L1"}, {"id": "admin_homework_filters_inputstyle", "label": "inputStyle", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/homework-filters.tsx", "source_location": "L7"}, {"id": "admin_homework_filters_course", "label": "Course", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/homework-filters.tsx", "source_location": "L16"}, {"id": "admin_homework_filters_homeworkfilters", "label": "HomeworkFilters()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/homework-filters.tsx", "source_location": "L18"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_components_admin_homework_filters_tsx", "target": "navigation", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/homework-filters.tsx", "source_location": "L3", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_admin_homework_filters_tsx", "target": "react", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/homework-filters.tsx", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_admin_homework_filters_tsx", "target": "lucide_react", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/homework-filters.tsx", "source_location": "L5", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_admin_homework_filters_tsx", "target": "admin_homework_filters_inputstyle", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/homework-filters.tsx", "source_location": "L7", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_admin_homework_filters_tsx", "target": "admin_homework_filters_course", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/homework-filters.tsx", "source_location": "L16", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_admin_homework_filters_tsx", "target": "admin_homework_filters_homeworkfilters", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/homework-filters.tsx", "source_location": "L18", "weight": 1.0}], "raw_calls": [{"caller_nid": "admin_homework_filters_homeworkfilters", "callee": "useRouter", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/homework-filters.tsx", "source_location": "L19"}, {"caller_nid": "admin_homework_filters_homeworkfilters", "callee": "usePathname", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/homework-filters.tsx", "source_location": "L20"}, {"caller_nid": "admin_homework_filters_homeworkfilters", "callee": "useSearchParams", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/homework-filters.tsx", "source_location": "L21"}, {"caller_nid": "admin_homework_filters_homeworkfilters", "callee": "useTransition", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/homework-filters.tsx", "source_location": "L22"}, {"caller_nid": "admin_homework_filters_homeworkfilters", "callee": "get", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/homework-filters.tsx", "source_location": "L32"}, {"caller_nid": "admin_homework_filters_homeworkfilters", "callee": "get", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/homework-filters.tsx", "source_location": "L33"}, {"caller_nid": "admin_homework_filters_homeworkfilters", "callee": "get", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/homework-filters.tsx", "source_location": "L34"}, {"caller_nid": "admin_homework_filters_homeworkfilters", "callee": "map", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/homework-filters.tsx", "source_location": "L82"}]}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_postcss_config_mjs", "label": "postcss.config.mjs", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/postcss.config.mjs", "source_location": "L1"}, {"id": "lms_system_postcss_config_config", "label": "config", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/postcss.config.mjs", "source_location": "L1"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_postcss_config_mjs", "target": "lms_system_postcss_config_config", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/postcss.config.mjs", "source_location": "L1", "weight": 1.0}], "raw_calls": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_app_auth_register_register_form_tsx", "label": "register-form.tsx", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/register/register-form.tsx", "source_location": "L1"}, {"id": "register_register_form_props", "label": "Props", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/register/register-form.tsx", "source_location": "L7"}, {"id": "register_register_form_registerform", "label": "RegisterForm()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/register/register-form.tsx", "source_location": "L14"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_app_auth_register_register_form_tsx", "target": "react", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/register/register-form.tsx", "source_location": "L3", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_auth_register_register_form_tsx", "target": "link", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/register/register-form.tsx", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_auth_register_register_form_tsx", "target": "users_dementiy_documents_claude_lms_system_src_lib_auth_client_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/register/register-form.tsx", "source_location": "L5", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_auth_register_register_form_tsx", "target": "lib_auth_client_signup", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/register/register-form.tsx", "source_location": "L5", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_auth_register_register_form_tsx", "target": "register_register_form_props", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/register/register-form.tsx", "source_location": "L7", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_auth_register_register_form_tsx", "target": "register_register_form_registerform", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/register/register-form.tsx", "source_location": "L14", "weight": 1.0}], "raw_calls": [{"caller_nid": "register_register_form_registerform", "callee": "useState", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/register/register-form.tsx", "source_location": "L15"}, {"caller_nid": "register_register_form_registerform", "callee": "useState", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/register/register-form.tsx", "source_location": "L16"}, {"caller_nid": "register_register_form_registerform", "callee": "useState", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/register/register-form.tsx", "source_location": "L17"}, {"caller_nid": "register_register_form_registerform", "callee": "useState", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/register/register-form.tsx", "source_location": "L18"}, {"caller_nid": "register_register_form_registerform", "callee": "useState", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/register/register-form.tsx", "source_location": "L19"}, {"caller_nid": "register_register_form_registerform", "callee": "useState", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/register/register-form.tsx", "source_location": "L20"}, {"caller_nid": "register_register_form_registerform", "callee": "useState", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/register/register-form.tsx", "source_location": "L21"}, {"caller_nid": "register_register_form_registerform", "callee": "filter", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/register/register-form.tsx", "source_location": "L33"}, {"caller_nid": "register_register_form_registerform", "callee": "map", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/register/register-form.tsx", "source_location": "L136"}]}
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_lib_prisma_ts", "label": "prisma.ts", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/prisma.ts", "source_location": "L1"}, {"id": "lib_prisma_globalforprisma", "label": "globalForPrisma", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/prisma.ts", "source_location": "L4"}, {"id": "lib_prisma_createprismaclient", "label": "createPrismaClient()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/prisma.ts", "source_location": "L8"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_lib_prisma_ts", "target": "users_dementiy_documents_claude_lms_system_src_generated_prisma_client_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/prisma.ts", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_lib_prisma_ts", "target": "prisma_client_prismaclient", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/prisma.ts", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_lib_prisma_ts", "target": "adapter_pg", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/prisma.ts", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_lib_prisma_ts", "target": "lib_prisma_globalforprisma", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/prisma.ts", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_lib_prisma_ts", "target": "lib_prisma_createprismaclient", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/prisma.ts", "source_location": "L8", "weight": 1.0}], "raw_calls": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_app_student_profile_actions_ts", "label": "actions.ts", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(student)/profile/actions.ts", "source_location": "L1"}, {"id": "profile_actions_changepasswordaction", "label": "changePasswordAction()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(student)/profile/actions.ts", "source_location": "L8"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_app_student_profile_actions_ts", "target": "headers", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(student)/profile/actions.ts", "source_location": "L3", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_student_profile_actions_ts", "target": "users_dementiy_documents_claude_lms_system_src_lib_auth_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(student)/profile/actions.ts", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_student_profile_actions_ts", "target": "lib_auth_auth", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(student)/profile/actions.ts", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_student_profile_actions_ts", "target": "users_dementiy_documents_claude_lms_system_src_lib_prisma_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(student)/profile/actions.ts", "source_location": "L5", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_student_profile_actions_ts", "target": "lib_prisma_prisma", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(student)/profile/actions.ts", "source_location": "L5", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_student_profile_actions_ts", "target": "bcryptjs", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(student)/profile/actions.ts", "source_location": "L6", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_student_profile_actions_ts", "target": "profile_actions_changepasswordaction", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(student)/profile/actions.ts", "source_location": "L8", "weight": 1.0}], "raw_calls": [{"caller_nid": "profile_actions_changepasswordaction", "callee": "get", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(student)/profile/actions.ts", "source_location": "L9"}, {"caller_nid": "profile_actions_changepasswordaction", "callee": "get", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(student)/profile/actions.ts", "source_location": "L10"}, {"caller_nid": "profile_actions_changepasswordaction", "callee": "get", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(student)/profile/actions.ts", "source_location": "L11"}, {"caller_nid": "profile_actions_changepasswordaction", "callee": "getSession", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(student)/profile/actions.ts", "source_location": "L17"}, {"caller_nid": "profile_actions_changepasswordaction", "callee": "headers", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(student)/profile/actions.ts", "source_location": "L17"}, {"caller_nid": "profile_actions_changepasswordaction", "callee": "findFirst", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(student)/profile/actions.ts", "source_location": "L20"}, {"caller_nid": "profile_actions_changepasswordaction", "callee": "compare", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(student)/profile/actions.ts", "source_location": "L25"}, {"caller_nid": "profile_actions_changepasswordaction", "callee": "hash", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(student)/profile/actions.ts", "source_location": "L28"}, {"caller_nid": "profile_actions_changepasswordaction", "callee": "update", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(student)/profile/actions.ts", "source_location": "L29"}]}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_components_ui_textarea_tsx", "label": "textarea.tsx", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/textarea.tsx", "source_location": "L1"}, {"id": "ui_textarea_textarea", "label": "Textarea()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/textarea.tsx", "source_location": "L5"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_components_ui_textarea_tsx", "target": "react", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/textarea.tsx", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_ui_textarea_tsx", "target": "users_dementiy_documents_claude_lms_system_src_lib_utils_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/textarea.tsx", "source_location": "L3", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_ui_textarea_tsx", "target": "lib_utils_cn", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/textarea.tsx", "source_location": "L3", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_ui_textarea_tsx", "target": "ui_textarea_textarea", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/textarea.tsx", "source_location": "L5", "weight": 1.0}], "raw_calls": [{"caller_nid": "ui_textarea_textarea", "callee": "cn", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/textarea.tsx", "source_location": "L9"}]}
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_app_admin_quizzes_quizid_page_tsx", "label": "page.tsx", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/quizzes/[quizId]/page.tsx", "source_location": "L1"}, {"id": "quizid_page_props", "label": "Props", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/quizzes/[quizId]/page.tsx", "source_location": "L5"}, {"id": "quizid_page_adminquizattemptspage", "label": "AdminQuizAttemptsPage()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/quizzes/[quizId]/page.tsx", "source_location": "L9"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_app_admin_quizzes_quizid_page_tsx", "target": "users_dementiy_documents_claude_lms_system_src_lib_prisma_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/quizzes/[quizId]/page.tsx", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_quizzes_quizid_page_tsx", "target": "lib_prisma_prisma", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/quizzes/[quizId]/page.tsx", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_quizzes_quizid_page_tsx", "target": "navigation", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/quizzes/[quizId]/page.tsx", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_quizzes_quizid_page_tsx", "target": "link", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/quizzes/[quizId]/page.tsx", "source_location": "L3", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_quizzes_quizid_page_tsx", "target": "quizid_page_props", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/quizzes/[quizId]/page.tsx", "source_location": "L5", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_quizzes_quizid_page_tsx", "target": "quizid_page_adminquizattemptspage", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/quizzes/[quizId]/page.tsx", "source_location": "L9", "weight": 1.0}], "raw_calls": [{"caller_nid": "quizid_page_adminquizattemptspage", "callee": "findUnique", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/quizzes/[quizId]/page.tsx", "source_location": "L12"}, {"caller_nid": "quizid_page_adminquizattemptspage", "callee": "notFound", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/quizzes/[quizId]/page.tsx", "source_location": "L30"}, {"caller_nid": "quizid_page_adminquizattemptspage", "callee": "map", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/quizzes/[quizId]/page.tsx", "source_location": "L32"}, {"caller_nid": "quizid_page_adminquizattemptspage", "callee": "findMany", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/quizzes/[quizId]/page.tsx", "source_location": "L33"}, {"caller_nid": "quizid_page_adminquizattemptspage", "callee": "fromEntries", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/quizzes/[quizId]/page.tsx", "source_location": "L37"}, {"caller_nid": "quizid_page_adminquizattemptspage", "callee": "map", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/quizzes/[quizId]/page.tsx", "source_location": "L37"}, {"caller_nid": "quizid_page_adminquizattemptspage", "callee": "map", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/quizzes/[quizId]/page.tsx", "source_location": "L65"}]}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_app_admin_settings_page_tsx", "label": "page.tsx", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/settings/page.tsx", "source_location": "L1"}, {"id": "settings_page_metadata", "label": "metadata", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/settings/page.tsx", "source_location": "L4"}, {"id": "settings_page_settingspage", "label": "SettingsPage()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/settings/page.tsx", "source_location": "L6"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_app_admin_settings_page_tsx", "target": "users_dementiy_documents_claude_lms_system_src_lib_settings_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/settings/page.tsx", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_settings_page_tsx", "target": "lib_settings_getsettings", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/settings/page.tsx", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_settings_page_tsx", "target": "users_dementiy_documents_claude_lms_system_src_components_admin_settings_form_tsx", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/settings/page.tsx", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_settings_page_tsx", "target": "admin_settings_form_settingsform", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/settings/page.tsx", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_settings_page_tsx", "target": "settings_page_metadata", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/settings/page.tsx", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_settings_page_tsx", "target": "settings_page_settingspage", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/settings/page.tsx", "source_location": "L6", "weight": 1.0}], "raw_calls": [{"caller_nid": "settings_page_settingspage", "callee": "getSettings", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/settings/page.tsx", "source_location": "L7"}]}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_components_ui_badge_tsx", "label": "badge.tsx", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/badge.tsx", "source_location": "L1"}, {"id": "ui_badge_badgevariants", "label": "badgeVariants", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/badge.tsx", "source_location": "L7"}, {"id": "ui_badge_badge", "label": "Badge()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/badge.tsx", "source_location": "L30"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_components_ui_badge_tsx", "target": "merge_props", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/badge.tsx", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_ui_badge_tsx", "target": "use_render", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/badge.tsx", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_ui_badge_tsx", "target": "class_variance_authority", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/badge.tsx", "source_location": "L3", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_ui_badge_tsx", "target": "users_dementiy_documents_claude_lms_system_src_lib_utils_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/badge.tsx", "source_location": "L5", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_ui_badge_tsx", "target": "lib_utils_cn", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/badge.tsx", "source_location": "L5", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_ui_badge_tsx", "target": "ui_badge_badgevariants", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/badge.tsx", "source_location": "L7", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_ui_badge_tsx", "target": "ui_badge_badge", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/badge.tsx", "source_location": "L30", "weight": 1.0}, {"source": "ui_badge_badge", "target": "ui_badge_badgevariants", "relation": "calls", "context": "call", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/badge.tsx", "source_location": "L40", "weight": 1.0}], "raw_calls": [{"caller_nid": "ui_badge_badge", "callee": "useRender", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/badge.tsx", "source_location": "L36"}, {"caller_nid": "ui_badge_badge", "callee": "mergeProps", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/badge.tsx", "source_location": "L38"}, {"caller_nid": "ui_badge_badge", "callee": "cn", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/badge.tsx", "source_location": "L40"}]}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_app_auth_login_page_tsx", "label": "page.tsx", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/login/page.tsx", "source_location": "L1"}, {"id": "login_page_loginpage", "label": "LoginPage()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/login/page.tsx", "source_location": "L4"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_app_auth_login_page_tsx", "target": "users_dementiy_documents_claude_lms_system_src_lib_settings_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/login/page.tsx", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_auth_login_page_tsx", "target": "lib_settings_getsetting", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/login/page.tsx", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_auth_login_page_tsx", "target": "users_dementiy_documents_claude_lms_system_src_app_auth_login_login_form_tsx", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/login/page.tsx", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_auth_login_page_tsx", "target": "login_login_form_loginform", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/login/page.tsx", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_auth_login_page_tsx", "target": "login_page_loginpage", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/login/page.tsx", "source_location": "L4", "weight": 1.0}], "raw_calls": [{"caller_nid": "login_page_loginpage", "callee": "all", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/login/page.tsx", "source_location": "L9"}, {"caller_nid": "login_page_loginpage", "callee": "getSetting", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/login/page.tsx", "source_location": "L10"}]}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_components_admin_admin_nav_tsx", "label": "admin-nav.tsx", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/admin-nav.tsx", "source_location": "L1"}, {"id": "admin_admin_nav_links", "label": "links", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/admin-nav.tsx", "source_location": "L6"}, {"id": "admin_admin_nav_adminnav", "label": "AdminNav()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/admin-nav.tsx", "source_location": "L19"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_components_admin_admin_nav_tsx", "target": "link", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/admin-nav.tsx", "source_location": "L3", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_admin_admin_nav_tsx", "target": "navigation", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/admin-nav.tsx", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_admin_admin_nav_tsx", "target": "admin_admin_nav_links", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/admin-nav.tsx", "source_location": "L6", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_admin_admin_nav_tsx", "target": "admin_admin_nav_adminnav", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/admin-nav.tsx", "source_location": "L19", "weight": 1.0}], "raw_calls": [{"caller_nid": "admin_admin_nav_adminnav", "callee": "usePathname", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/admin-nav.tsx", "source_location": "L20"}, {"caller_nid": "admin_admin_nav_adminnav", "callee": "map", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/admin-nav.tsx", "source_location": "L24"}]}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_app_auth_register_page_tsx", "label": "page.tsx", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/register/page.tsx", "source_location": "L1"}, {"id": "register_page_registerpage", "label": "RegisterPage()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/register/page.tsx", "source_location": "L5"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_app_auth_register_page_tsx", "target": "navigation", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/register/page.tsx", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_auth_register_page_tsx", "target": "users_dementiy_documents_claude_lms_system_src_lib_settings_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/register/page.tsx", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_auth_register_page_tsx", "target": "lib_settings_getsettings", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/register/page.tsx", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_auth_register_page_tsx", "target": "users_dementiy_documents_claude_lms_system_src_app_auth_register_register_form_tsx", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/register/page.tsx", "source_location": "L3", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_auth_register_page_tsx", "target": "register_register_form_registerform", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/register/page.tsx", "source_location": "L3", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_auth_register_page_tsx", "target": "register_page_registerpage", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/register/page.tsx", "source_location": "L5", "weight": 1.0}], "raw_calls": [{"caller_nid": "register_page_registerpage", "callee": "getSettings", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/register/page.tsx", "source_location": "L6"}, {"caller_nid": "register_page_registerpage", "callee": "redirect", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/register/page.tsx", "source_location": "L9"}]}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_components_ui_label_tsx", "label": "label.tsx", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/label.tsx", "source_location": "L1"}, {"id": "ui_label_label", "label": "Label()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/label.tsx", "source_location": "L7"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_components_ui_label_tsx", "target": "react", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/label.tsx", "source_location": "L3", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_ui_label_tsx", "target": "users_dementiy_documents_claude_lms_system_src_lib_utils_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/label.tsx", "source_location": "L5", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_ui_label_tsx", "target": "lib_utils_cn", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/label.tsx", "source_location": "L5", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_ui_label_tsx", "target": "ui_label_label", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/label.tsx", "source_location": "L7", "weight": 1.0}], "raw_calls": [{"caller_nid": "ui_label_label", "callee": "cn", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/label.tsx", "source_location": "L11"}]}
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_lib_s3_ts", "label": "s3.ts", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/s3.ts", "source_location": "L1"}, {"id": "lib_s3_s3", "label": "s3", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/s3.ts", "source_location": "L4"}, {"id": "lib_s3_getpublicurl", "label": "getPublicUrl()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/s3.ts", "source_location": "L16"}, {"id": "lib_s3_uploadfile", "label": "uploadFile()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/s3.ts", "source_location": "L20"}, {"id": "lib_s3_deletefile", "label": "deleteFile()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/s3.ts", "source_location": "L36"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_lib_s3_ts", "target": "client_s3", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/s3.ts", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_lib_s3_ts", "target": "s3_request_presigner", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/s3.ts", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_lib_s3_ts", "target": "lib_s3_s3", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/s3.ts", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_lib_s3_ts", "target": "lib_s3_getpublicurl", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/s3.ts", "source_location": "L16", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_lib_s3_ts", "target": "lib_s3_uploadfile", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/s3.ts", "source_location": "L20", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_lib_s3_ts", "target": "lib_s3_deletefile", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/s3.ts", "source_location": "L36", "weight": 1.0}, {"source": "lib_s3_uploadfile", "target": "lib_s3_getpublicurl", "relation": "calls", "context": "call", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/s3.ts", "source_location": "L33", "weight": 1.0}], "raw_calls": [{"caller_nid": "lib_s3_uploadfile", "callee": "send", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/s3.ts", "source_location": "L25"}, {"caller_nid": "lib_s3_deletefile", "callee": "send", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/s3.ts", "source_location": "L37"}]}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_components_admin_admin_shell_tsx", "label": "admin-shell.tsx", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/admin-shell.tsx", "source_location": "L1"}, {"id": "admin_admin_shell_adminshell", "label": "AdminShell()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/admin-shell.tsx", "source_location": "L4"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_components_admin_admin_shell_tsx", "target": "users_dementiy_documents_claude_lms_system_src_components_admin_admin_nav_tsx", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/admin-shell.tsx", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_admin_admin_shell_tsx", "target": "admin_admin_nav_adminnav", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/admin-shell.tsx", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_admin_admin_shell_tsx", "target": "users_dementiy_documents_claude_lms_system_src_components_layout_logout_button_tsx", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/admin-shell.tsx", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_admin_admin_shell_tsx", "target": "layout_logout_button_logoutbutton", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/admin-shell.tsx", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_admin_admin_shell_tsx", "target": "admin_admin_shell_adminshell", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/admin-shell.tsx", "source_location": "L4", "weight": 1.0}], "raw_calls": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_eslint_config_mjs", "label": "eslint.config.mjs", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/eslint.config.mjs", "source_location": "L1"}, {"id": "lms_system_eslint_config_eslintconfig", "label": "eslintConfig", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/eslint.config.mjs", "source_location": "L5"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_eslint_config_mjs", "target": "config", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/eslint.config.mjs", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_eslint_config_mjs", "target": "core_web_vitals", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/eslint.config.mjs", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_eslint_config_mjs", "target": "typescript", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/eslint.config.mjs", "source_location": "L3", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_eslint_config_mjs", "target": "lms_system_eslint_config_eslintconfig", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/eslint.config.mjs", "source_location": "L5", "weight": 1.0}], "raw_calls": []}
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_app_admin_comments_delete_action_ts", "label": "delete-action.ts", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/comments/delete-action.ts", "source_location": "L1"}, {"id": "comments_delete_action_deletecomment", "label": "deleteComment()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/comments/delete-action.ts", "source_location": "L8"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_app_admin_comments_delete_action_ts", "target": "headers", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/comments/delete-action.ts", "source_location": "L3", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_comments_delete_action_ts", "target": "users_dementiy_documents_claude_lms_system_src_lib_auth_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/comments/delete-action.ts", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_comments_delete_action_ts", "target": "lib_auth_auth", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/comments/delete-action.ts", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_comments_delete_action_ts", "target": "users_dementiy_documents_claude_lms_system_src_lib_prisma_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/comments/delete-action.ts", "source_location": "L5", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_comments_delete_action_ts", "target": "lib_prisma_prisma", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/comments/delete-action.ts", "source_location": "L5", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_comments_delete_action_ts", "target": "cache", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/comments/delete-action.ts", "source_location": "L6", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_comments_delete_action_ts", "target": "comments_delete_action_deletecomment", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/comments/delete-action.ts", "source_location": "L8", "weight": 1.0}], "raw_calls": [{"caller_nid": "comments_delete_action_deletecomment", "callee": "getSession", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/comments/delete-action.ts", "source_location": "L9"}, {"caller_nid": "comments_delete_action_deletecomment", "callee": "headers", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/comments/delete-action.ts", "source_location": "L9"}, {"caller_nid": "comments_delete_action_deletecomment", "callee": "update", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/comments/delete-action.ts", "source_location": "L12"}, {"caller_nid": "comments_delete_action_deletecomment", "callee": "revalidatePath", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/comments/delete-action.ts", "source_location": "L17"}]}
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_components_ui_button_tsx", "label": "button.tsx", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/button.tsx", "source_location": "L1"}, {"id": "ui_button_buttonvariants", "label": "buttonVariants", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/button.tsx", "source_location": "L6"}, {"id": "ui_button_button", "label": "Button()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/button.tsx", "source_location": "L43"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_components_ui_button_tsx", "target": "button", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/button.tsx", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_ui_button_tsx", "target": "class_variance_authority", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/button.tsx", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_ui_button_tsx", "target": "users_dementiy_documents_claude_lms_system_src_lib_utils_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/button.tsx", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_ui_button_tsx", "target": "lib_utils_cn", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/button.tsx", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_ui_button_tsx", "target": "ui_button_buttonvariants", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/button.tsx", "source_location": "L6", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_ui_button_tsx", "target": "ui_button_button", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/button.tsx", "source_location": "L43", "weight": 1.0}, {"source": "ui_button_button", "target": "ui_button_buttonvariants", "relation": "calls", "context": "call", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/button.tsx", "source_location": "L52", "weight": 1.0}], "raw_calls": [{"caller_nid": "ui_button_button", "callee": "cn", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/button.tsx", "source_location": "L52"}]}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_entrypoint_sh", "label": "entrypoint.sh", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/entrypoint.sh", "source_location": "L1"}], "edges": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_app_auth_forgot_password_page_tsx", "label": "page.tsx", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/forgot-password/page.tsx", "source_location": "L1"}, {"id": "forgot_password_page_forgotpasswordpage", "label": "ForgotPasswordPage()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/forgot-password/page.tsx", "source_location": "L4"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_app_auth_forgot_password_page_tsx", "target": "users_dementiy_documents_claude_lms_system_src_lib_settings_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/forgot-password/page.tsx", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_auth_forgot_password_page_tsx", "target": "lib_settings_getsetting", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/forgot-password/page.tsx", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_auth_forgot_password_page_tsx", "target": "users_dementiy_documents_claude_lms_system_src_app_auth_forgot_password_forgot_password_form_tsx", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/forgot-password/page.tsx", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_auth_forgot_password_page_tsx", "target": "forgot_password_forgot_password_form_forgotpasswordform", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/forgot-password/page.tsx", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_auth_forgot_password_page_tsx", "target": "forgot_password_page_forgotpasswordpage", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/forgot-password/page.tsx", "source_location": "L4", "weight": 1.0}], "raw_calls": [{"caller_nid": "forgot_password_page_forgotpasswordpage", "callee": "getSetting", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/forgot-password/page.tsx", "source_location": "L5"}]}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_components_ui_input_tsx", "label": "input.tsx", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/input.tsx", "source_location": "L1"}, {"id": "ui_input_input", "label": "Input()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/input.tsx", "source_location": "L6"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_components_ui_input_tsx", "target": "react", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/input.tsx", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_ui_input_tsx", "target": "input", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/input.tsx", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_ui_input_tsx", "target": "users_dementiy_documents_claude_lms_system_src_lib_utils_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/input.tsx", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_ui_input_tsx", "target": "lib_utils_cn", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/input.tsx", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_ui_input_tsx", "target": "ui_input_input", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/input.tsx", "source_location": "L6", "weight": 1.0}], "raw_calls": [{"caller_nid": "ui_input_input", "callee": "cn", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/ui/input.tsx", "source_location": "L11"}]}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_app_admin_questions_page_tsx", "label": "page.tsx", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/questions/page.tsx", "source_location": "L1"}, {"id": "questions_page_adminquestionspage", "label": "AdminQuestionsPage()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/questions/page.tsx", "source_location": "L6"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_app_admin_questions_page_tsx", "target": "headers", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/questions/page.tsx", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_questions_page_tsx", "target": "users_dementiy_documents_claude_lms_system_src_lib_auth_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/questions/page.tsx", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_questions_page_tsx", "target": "lib_auth_auth", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/questions/page.tsx", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_questions_page_tsx", "target": "navigation", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/questions/page.tsx", "source_location": "L3", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_questions_page_tsx", "target": "users_dementiy_documents_claude_lms_system_src_components_questions_questionsplitview_tsx", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/questions/page.tsx", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_questions_page_tsx", "target": "questions_questionsplitview_questionsplitview", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/questions/page.tsx", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_questions_page_tsx", "target": "questions_page_adminquestionspage", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/questions/page.tsx", "source_location": "L6", "weight": 1.0}], "raw_calls": [{"caller_nid": "questions_page_adminquestionspage", "callee": "getSession", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/questions/page.tsx", "source_location": "L7"}, {"caller_nid": "questions_page_adminquestionspage", "callee": "headers", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/questions/page.tsx", "source_location": "L7"}, {"caller_nid": "questions_page_adminquestionspage", "callee": "redirect", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/questions/page.tsx", "source_location": "L8"}]}
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_app_auth_verify_email_page_tsx", "label": "page.tsx", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/verify-email/page.tsx", "source_location": "L1"}, {"id": "verify_email_page_verifyemailpage", "label": "VerifyEmailPage()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/verify-email/page.tsx", "source_location": "L3"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_app_auth_verify_email_page_tsx", "target": "link", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/verify-email/page.tsx", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_auth_verify_email_page_tsx", "target": "verify_email_page_verifyemailpage", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(auth)/verify-email/page.tsx", "source_location": "L3", "weight": 1.0}], "raw_calls": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_app_admin_layout_tsx", "label": "layout.tsx", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/layout.tsx", "source_location": "L1"}, {"id": "admin_layout_adminlayout", "label": "AdminLayout()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/layout.tsx", "source_location": "L7"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_app_admin_layout_tsx", "target": "headers", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/layout.tsx", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_layout_tsx", "target": "users_dementiy_documents_claude_lms_system_src_lib_auth_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/layout.tsx", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_layout_tsx", "target": "lib_auth_auth", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/layout.tsx", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_layout_tsx", "target": "navigation", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/layout.tsx", "source_location": "L3", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_layout_tsx", "target": "users_dementiy_documents_claude_lms_system_src_components_admin_admin_shell_tsx", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/layout.tsx", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_layout_tsx", "target": "admin_admin_shell_adminshell", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/layout.tsx", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_layout_tsx", "target": "users_dementiy_documents_claude_lms_system_src_lib_prisma_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/layout.tsx", "source_location": "L5", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_layout_tsx", "target": "lib_prisma_prisma", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/layout.tsx", "source_location": "L5", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_layout_tsx", "target": "admin_layout_adminlayout", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/layout.tsx", "source_location": "L7", "weight": 1.0}], "raw_calls": [{"caller_nid": "admin_layout_adminlayout", "callee": "getSession", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/layout.tsx", "source_location": "L8"}, {"caller_nid": "admin_layout_adminlayout", "callee": "headers", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/layout.tsx", "source_location": "L8"}, {"caller_nid": "admin_layout_adminlayout", "callee": "redirect", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/layout.tsx", "source_location": "L9"}, {"caller_nid": "admin_layout_adminlayout", "callee": "redirect", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/layout.tsx", "source_location": "L10"}, {"caller_nid": "admin_layout_adminlayout", "callee": "count", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/layout.tsx", "source_location": "L12"}]}
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_app_admin_users_new_page_tsx", "label": "page.tsx", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/users/new/page.tsx", "source_location": "L1"}, {"id": "new_page_metadata", "label": "metadata", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/users/new/page.tsx", "source_location": "L4"}, {"id": "new_page_newuserpage", "label": "NewUserPage()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/users/new/page.tsx", "source_location": "L6"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_app_admin_users_new_page_tsx", "target": "link", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/users/new/page.tsx", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_users_new_page_tsx", "target": "users_dementiy_documents_claude_lms_system_src_components_admin_create_user_form_tsx", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/users/new/page.tsx", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_users_new_page_tsx", "target": "admin_create_user_form_createuserform", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/users/new/page.tsx", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_users_new_page_tsx", "target": "new_page_metadata", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/users/new/page.tsx", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_users_new_page_tsx", "target": "new_page_newuserpage", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/users/new/page.tsx", "source_location": "L6", "weight": 1.0}], "raw_calls": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_app_api_questions_id_close_route_ts", "label": "route.ts", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/api/questions/[id]/close/route.ts", "source_location": "L1"}, {"id": "close_route_patch", "label": "PATCH()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/api/questions/[id]/close/route.ts", "source_location": "L6"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_app_api_questions_id_close_route_ts", "target": "server", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/api/questions/[id]/close/route.ts", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_api_questions_id_close_route_ts", "target": "headers", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/api/questions/[id]/close/route.ts", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_api_questions_id_close_route_ts", "target": "users_dementiy_documents_claude_lms_system_src_lib_auth_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/api/questions/[id]/close/route.ts", "source_location": "L3", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_api_questions_id_close_route_ts", "target": "lib_auth_auth", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/api/questions/[id]/close/route.ts", "source_location": "L3", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_api_questions_id_close_route_ts", "target": "users_dementiy_documents_claude_lms_system_src_lib_prisma_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/api/questions/[id]/close/route.ts", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_api_questions_id_close_route_ts", "target": "lib_prisma_prisma", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/api/questions/[id]/close/route.ts", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_api_questions_id_close_route_ts", "target": "close_route_patch", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/api/questions/[id]/close/route.ts", "source_location": "L6", "weight": 1.0}], "raw_calls": [{"caller_nid": "close_route_patch", "callee": "getSession", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/api/questions/[id]/close/route.ts", "source_location": "L10"}, {"caller_nid": "close_route_patch", "callee": "headers", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/api/questions/[id]/close/route.ts", "source_location": "L10"}, {"caller_nid": "close_route_patch", "callee": "json", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/api/questions/[id]/close/route.ts", "source_location": "L11"}, {"caller_nid": "close_route_patch", "callee": "json", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/api/questions/[id]/close/route.ts", "source_location": "L14"}, {"caller_nid": "close_route_patch", "callee": "findUnique", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/api/questions/[id]/close/route.ts", "source_location": "L19"}, {"caller_nid": "close_route_patch", "callee": "json", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/api/questions/[id]/close/route.ts", "source_location": "L20"}, {"caller_nid": "close_route_patch", "callee": "json", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/api/questions/[id]/close/route.ts", "source_location": "L22"}, {"caller_nid": "close_route_patch", "callee": "update", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/api/questions/[id]/close/route.ts", "source_location": "L25"}, {"caller_nid": "close_route_patch", "callee": "json", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/api/questions/[id]/close/route.ts", "source_location": "L30"}]}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_app_admin_quizzes_page_tsx", "label": "page.tsx", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/quizzes/page.tsx", "source_location": "L1"}, {"id": "quizzes_page_metadata", "label": "metadata", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/quizzes/page.tsx", "source_location": "L4"}, {"id": "quizzes_page_adminquizzespage", "label": "AdminQuizzesPage()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/quizzes/page.tsx", "source_location": "L6"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_app_admin_quizzes_page_tsx", "target": "users_dementiy_documents_claude_lms_system_src_lib_prisma_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/quizzes/page.tsx", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_quizzes_page_tsx", "target": "lib_prisma_prisma", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/quizzes/page.tsx", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_quizzes_page_tsx", "target": "link", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/quizzes/page.tsx", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_quizzes_page_tsx", "target": "quizzes_page_metadata", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/quizzes/page.tsx", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_quizzes_page_tsx", "target": "quizzes_page_adminquizzespage", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/quizzes/page.tsx", "source_location": "L6", "weight": 1.0}], "raw_calls": [{"caller_nid": "quizzes_page_adminquizzespage", "callee": "findMany", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/quizzes/page.tsx", "source_location": "L7"}, {"caller_nid": "quizzes_page_adminquizzespage", "callee": "map", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/quizzes/page.tsx", "source_location": "L44"}]}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_app_student_courses_slug_page_tsx", "label": "page.tsx", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(student)/courses/[slug]/page.tsx", "source_location": "L1"}, {"id": "slug_page_props", "label": "Props", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(student)/courses/[slug]/page.tsx", "source_location": "L5"}, {"id": "slug_page_coursepage", "label": "CoursePage()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(student)/courses/[slug]/page.tsx", "source_location": "L9"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_app_student_courses_slug_page_tsx", "target": "users_dementiy_documents_claude_lms_system_src_lib_prisma_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(student)/courses/[slug]/page.tsx", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_student_courses_slug_page_tsx", "target": "lib_prisma_prisma", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(student)/courses/[slug]/page.tsx", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_student_courses_slug_page_tsx", "target": "navigation", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(student)/courses/[slug]/page.tsx", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_student_courses_slug_page_tsx", "target": "navigation", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(student)/courses/[slug]/page.tsx", "source_location": "L3", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_student_courses_slug_page_tsx", "target": "slug_page_props", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(student)/courses/[slug]/page.tsx", "source_location": "L5", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_student_courses_slug_page_tsx", "target": "slug_page_coursepage", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(student)/courses/[slug]/page.tsx", "source_location": "L9", "weight": 1.0}], "raw_calls": [{"caller_nid": "slug_page_coursepage", "callee": "findUnique", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(student)/courses/[slug]/page.tsx", "source_location": "L12"}, {"caller_nid": "slug_page_coursepage", "callee": "notFound", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(student)/courses/[slug]/page.tsx", "source_location": "L29"}, {"caller_nid": "slug_page_coursepage", "callee": "redirect", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/(student)/courses/[slug]/page.tsx", "source_location": "L34"}]}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_components_admin_csv_exporter_tsx", "label": "csv-exporter.tsx", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/csv-exporter.tsx", "source_location": "L1"}, {"id": "admin_csv_exporter_course", "label": "Course", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/csv-exporter.tsx", "source_location": "L6"}, {"id": "admin_csv_exporter_inputstyle", "label": "inputStyle", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/csv-exporter.tsx", "source_location": "L8"}, {"id": "admin_csv_exporter_focushandlers", "label": "focusHandlers", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/csv-exporter.tsx", "source_location": "L17"}, {"id": "admin_csv_exporter_csvexporter", "label": "CsvExporter()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/csv-exporter.tsx", "source_location": "L24"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_components_admin_csv_exporter_tsx", "target": "react", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/csv-exporter.tsx", "source_location": "L3", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_admin_csv_exporter_tsx", "target": "lucide_react", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/csv-exporter.tsx", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_admin_csv_exporter_tsx", "target": "admin_csv_exporter_course", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/csv-exporter.tsx", "source_location": "L6", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_admin_csv_exporter_tsx", "target": "admin_csv_exporter_inputstyle", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/csv-exporter.tsx", "source_location": "L8", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_admin_csv_exporter_tsx", "target": "admin_csv_exporter_focushandlers", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/csv-exporter.tsx", "source_location": "L17", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_admin_csv_exporter_tsx", "target": "admin_csv_exporter_csvexporter", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/csv-exporter.tsx", "source_location": "L24", "weight": 1.0}], "raw_calls": [{"caller_nid": "admin_csv_exporter_csvexporter", "callee": "useState", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/csv-exporter.tsx", "source_location": "L25"}, {"caller_nid": "admin_csv_exporter_csvexporter", "callee": "useState", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/csv-exporter.tsx", "source_location": "L26"}, {"caller_nid": "admin_csv_exporter_csvexporter", "callee": "useState", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/csv-exporter.tsx", "source_location": "L27"}, {"caller_nid": "admin_csv_exporter_csvexporter", "callee": "map", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/admin/csv-exporter.tsx", "source_location": "L60"}]}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_components_curator_audio_recorder_tsx", "label": "audio-recorder.tsx", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/curator/audio-recorder.tsx", "source_location": "L1"}, {"id": "curator_audio_recorder_audiorecorderprops", "label": "AudioRecorderProps", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/curator/audio-recorder.tsx", "source_location": "L5"}, {"id": "curator_audio_recorder_audiorecorder", "label": "AudioRecorder()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/curator/audio-recorder.tsx", "source_location": "L11"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_components_curator_audio_recorder_tsx", "target": "react", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/curator/audio-recorder.tsx", "source_location": "L3", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_curator_audio_recorder_tsx", "target": "curator_audio_recorder_audiorecorderprops", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/curator/audio-recorder.tsx", "source_location": "L5", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_components_curator_audio_recorder_tsx", "target": "curator_audio_recorder_audiorecorder", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/curator/audio-recorder.tsx", "source_location": "L11", "weight": 1.0}], "raw_calls": [{"caller_nid": "curator_audio_recorder_audiorecorder", "callee": "useState", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/curator/audio-recorder.tsx", "source_location": "L12"}, {"caller_nid": "curator_audio_recorder_audiorecorder", "callee": "useState", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/curator/audio-recorder.tsx", "source_location": "L13"}, {"caller_nid": "curator_audio_recorder_audiorecorder", "callee": "useRef", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/curator/audio-recorder.tsx", "source_location": "L14"}, {"caller_nid": "curator_audio_recorder_audiorecorder", "callee": "useRef", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/curator/audio-recorder.tsx", "source_location": "L15"}, {"caller_nid": "curator_audio_recorder_audiorecorder", "callee": "useRef", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/components/curator/audio-recorder.tsx", "source_location": "L16"}]}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_next_config_ts", "label": "next.config.ts", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/next.config.ts", "source_location": "L1"}, {"id": "lms_system_next_config_nextconfig", "label": "nextConfig", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/next.config.ts", "source_location": "L3"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_next_config_ts", "target": "next", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/next.config.ts", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_next_config_ts", "target": "lms_system_next_config_nextconfig", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/next.config.ts", "source_location": "L3", "weight": 1.0}], "raw_calls": []}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_app_curator_homework_submissionid_content_tabs_tsx", "label": "content-tabs.tsx", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/curator/homework/[submissionId]/content-tabs.tsx", "source_location": "L1"}, {"id": "submissionid_content_tabs_props", "label": "Props", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/curator/homework/[submissionId]/content-tabs.tsx", "source_location": "L6"}, {"id": "submissionid_content_tabs_contenttabs", "label": "ContentTabs()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/curator/homework/[submissionId]/content-tabs.tsx", "source_location": "L11"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_app_curator_homework_submissionid_content_tabs_tsx", "target": "react", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/curator/homework/[submissionId]/content-tabs.tsx", "source_location": "L3", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_curator_homework_submissionid_content_tabs_tsx", "target": "users_dementiy_documents_claude_lms_system_src_components_curator_content_viewer_tsx", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/curator/homework/[submissionId]/content-tabs.tsx", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_curator_homework_submissionid_content_tabs_tsx", "target": "curator_content_viewer_contentviewer", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/curator/homework/[submissionId]/content-tabs.tsx", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_curator_homework_submissionid_content_tabs_tsx", "target": "submissionid_content_tabs_props", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/curator/homework/[submissionId]/content-tabs.tsx", "source_location": "L6", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_curator_homework_submissionid_content_tabs_tsx", "target": "submissionid_content_tabs_contenttabs", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/curator/homework/[submissionId]/content-tabs.tsx", "source_location": "L11", "weight": 1.0}], "raw_calls": [{"caller_nid": "submissionid_content_tabs_contenttabs", "callee": "useState", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/curator/homework/[submissionId]/content-tabs.tsx", "source_location": "L12"}, {"caller_nid": "submissionid_content_tabs_contenttabs", "callee": "map", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/curator/homework/[submissionId]/content-tabs.tsx", "source_location": "L18"}]}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_lib_auth_ts", "label": "auth.ts", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/auth.ts", "source_location": "L1"}, {"id": "lib_auth_auth", "label": "auth", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/auth.ts", "source_location": "L8"}, {"id": "lib_auth_session", "label": "Session", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/auth.ts", "source_location": "L53"}, {"id": "lib_auth_user", "label": "User", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/auth.ts", "source_location": "L54"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_lib_auth_ts", "target": "better_auth", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/auth.ts", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_lib_auth_ts", "target": "prisma", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/auth.ts", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_lib_auth_ts", "target": "plugins", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/auth.ts", "source_location": "L3", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_lib_auth_ts", "target": "users_dementiy_documents_claude_lms_system_src_lib_prisma_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/auth.ts", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_lib_auth_ts", "target": "lib_prisma_prisma", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/auth.ts", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_lib_auth_ts", "target": "bcryptjs", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/auth.ts", "source_location": "L5", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_lib_auth_ts", "target": "users_dementiy_documents_claude_lms_system_src_lib_email_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/auth.ts", "source_location": "L6", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_lib_auth_ts", "target": "lib_email_sendwelcomeemail", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/auth.ts", "source_location": "L6", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_lib_auth_ts", "target": "lib_email_sendpasswordresetemail", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/auth.ts", "source_location": "L6", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_lib_auth_ts", "target": "lib_auth_auth", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/auth.ts", "source_location": "L8", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_lib_auth_ts", "target": "lib_auth_session", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/auth.ts", "source_location": "L53", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_lib_auth_ts", "target": "lib_auth_user", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/auth.ts", "source_location": "L54", "weight": 1.0}], "raw_calls": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_lib_utils_ts", "label": "utils.ts", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/utils.ts", "source_location": "L1"}, {"id": "lib_utils_cn", "label": "cn()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/utils.ts", "source_location": "L4"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_lib_utils_ts", "target": "clsx", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/utils.ts", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_lib_utils_ts", "target": "tailwind_merge", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/utils.ts", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_lib_utils_ts", "target": "lib_utils_cn", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/utils.ts", "source_location": "L4", "weight": 1.0}], "raw_calls": [{"caller_nid": "lib_utils_cn", "callee": "twMerge", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/utils.ts", "source_location": "L5"}, {"caller_nid": "lib_utils_cn", "callee": "clsx", "is_member_call": false, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/lib/utils.ts", "source_location": "L5"}]}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_dementiy_documents_claude_lms_system_src_app_admin_categories_page_tsx", "label": "page.tsx", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/categories/page.tsx", "source_location": "L1"}, {"id": "categories_page_categoriespage", "label": "CategoriesPage()", "file_type": "code", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/categories/page.tsx", "source_location": "L7"}], "edges": [{"source": "users_dementiy_documents_claude_lms_system_src_app_admin_categories_page_tsx", "target": "users_dementiy_documents_claude_lms_system_src_lib_prisma_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/categories/page.tsx", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_categories_page_tsx", "target": "lib_prisma_prisma", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/categories/page.tsx", "source_location": "L1", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_categories_page_tsx", "target": "users_dementiy_documents_claude_lms_system_src_components_admin_category_row_tsx", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/categories/page.tsx", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_categories_page_tsx", "target": "admin_category_row_categoryrow", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/categories/page.tsx", "source_location": "L2", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_categories_page_tsx", "target": "users_dementiy_documents_claude_lms_system_src_app_admin_categories_actions_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/categories/page.tsx", "source_location": "L3", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_categories_page_tsx", "target": "categories_actions_createcategory", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/categories/page.tsx", "source_location": "L3", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_categories_page_tsx", "target": "users_dementiy_documents_claude_lms_system_src_components_ui_button_tsx", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/categories/page.tsx", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_categories_page_tsx", "target": "ui_button_button", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/categories/page.tsx", "source_location": "L4", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_categories_page_tsx", "target": "users_dementiy_documents_claude_lms_system_src_components_ui_input_tsx", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/categories/page.tsx", "source_location": "L5", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_categories_page_tsx", "target": "ui_input_input", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/categories/page.tsx", "source_location": "L5", "weight": 1.0}, {"source": "users_dementiy_documents_claude_lms_system_src_app_admin_categories_page_tsx", "target": "categories_page_categoriespage", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/categories/page.tsx", "source_location": "L7", "weight": 1.0}], "raw_calls": [{"caller_nid": "categories_page_categoriespage", "callee": "findMany", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/categories/page.tsx", "source_location": "L8"}, {"caller_nid": "categories_page_categoriespage", "callee": "map", "is_member_call": true, "source_file": "/Users/dementiy/Documents/Claude/lms-system/src/app/admin/categories/page.tsx", "source_location": "L28"}]}

Some files were not shown because too many files have changed in this diff Show More