Skip to content

Comments

Adds embed route for RelatedAggregateGraph#516

Closed
codycooperross wants to merge 1 commit intomasterfrom
embed
Closed

Adds embed route for RelatedAggregateGraph#516
codycooperross wants to merge 1 commit intomasterfrom
embed

Conversation

@codycooperross
Copy link
Contributor

@codycooperross codycooperross commented Oct 7, 2025

Purpose

closes: Add github issue that originated this PR

Approach

Open Questions and Pre-Merge TODOs

Learning

Types of changes

  • Bug fix (non-breaking change which fixes an issue)

  • New feature (non-breaking change which adds functionality)

  • Breaking change (fix or feature that would cause existing functionality to change)

Reviewer, please remember our guidelines:

  • Be humble in the language and feedback you give, ask don't tell.
  • Consider using positive language as opposed to neutral when offering feedback. This is to avoid the negative bias that can occur with neutral language appearing negative.
  • Offer suggestions on how to improve code e.g. simplification or expanding clarity.
  • Ensure you give reasons for the changes you are proposing.

Summary by CodeRabbit

  • New Features
    • Added an embeddable page to display the Related Aggregate Graph for any DOI, suitable for full-viewport embedding.
    • Introduced an embed mode that optimizes the graph’s layout for iframes and external sites (removes column offset for a cleaner fit).

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 7, 2025

Walkthrough

Introduces an embed-specific route and layout for related aggregate graphs. Adds a page that composes a DOI from route params and renders RelatedAggregateGraph within Suspense, passing isEmbed=true. Updates RelatedAggregateGraph to accept an optional isEmbed prop that adjusts column offset behavior.

Changes

Cohort / File(s) Summary
Embed route page
src/app/(embed)/embed/related-aggregate/[...doi]/page.tsx
New page component that joins params.doi into a DOI string, renders RelatedAggregateGraph inside Suspense, and passes isEmbed={true}. Default export: EmbedRelatedAggregateGraphPage.
Embed layout
src/app/(embed)/embed/related-aggregate/layout.tsx
New layout wrapping children with html > body > div. Default export: EmbedLayout({ children }).
RelatedAggregateGraph prop update
src/app/doi.org/[...doi]/RelatedAggregateGraph.tsx
Adds optional isEmbed?: boolean prop (default false), and uses it to set Col offset to 0 when embedded, otherwise 3.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant U as Browser
    participant R as Next.js Router
    participant L as EmbedLayout
    participant P as EmbedRelatedAggregateGraphPage
    participant S as Suspense
    participant G as RelatedAggregateGraph

    U->>R: Request /embed/related-aggregate/{...doi}
    R->>L: Render layout
    L->>P: Render page with params.doi
    P->>P: Join params.doi with "/"
    P->>S: Wrap graph in Suspense
    S->>G: Render with { doi, isEmbed: true }
    note right of G: Uses isEmbed to set layout offset = 0
    G-->>U: Graph content (when ready)
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly and accurately describes the primary change of adding an embed route for the RelatedAggregateGraph component, matching the modifications made in the changeset. It is clear, specific, and free of unnecessary detail or ambiguity.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch embed

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
src/app/(embed)/embed/related-aggregate/[...doi]/page.tsx (1)

12-16: Consider adding error boundary or validation.

The component doesn't handle edge cases:

  • Missing or empty params.doi
  • Invalid DOI format
  • Errors during graph rendering

While the Suspense boundary handles loading states, consider wrapping the component with error handling, especially for an embeddable widget that external sites will use.

Example error handling:

export default async function EmbedRelatedAggregateGraphPage({ params }: Props) {
  const resolvedParams = await params;
  
  if (!resolvedParams.doi || resolvedParams.doi.length === 0) {
    return <div style={{ padding: '20px' }}>Invalid DOI</div>;
  }
  
  const doi = decodeURIComponent(resolvedParams.doi.join('/'));

  return (
    <div style={{ width: '100vw', height: '100vh', margin: 0, padding: 0 }}>
      <Suspense fallback={<div>Loading...</div>}>
        <RelatedAggregateGraph doi={doi} isEmbed={true} />
      </Suspense>
    </div>
  );
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ad308f1 and 59f8a89.

📒 Files selected for processing (3)
  • src/app/(embed)/embed/related-aggregate/[...doi]/page.tsx (1 hunks)
  • src/app/(embed)/embed/related-aggregate/layout.tsx (1 hunks)
  • src/app/doi.org/[...doi]/RelatedAggregateGraph.tsx (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
src/app/doi.org/[...doi]/RelatedAggregateGraph.tsx (1)
src/app/doi.org/[...doi]/RelatedContent.tsx (2)
  • Props (19-21)
  • RelatedContent (23-119)
src/app/(embed)/embed/related-aggregate/layout.tsx (1)
src/app/layout.tsx (1)
  • RootLayout (44-71)
src/app/(embed)/embed/related-aggregate/[...doi]/page.tsx (2)
src/app/doi.org/[...doi]/RelatedAggregateGraph.tsx (1)
  • RelatedAggregateGraph (38-79)
src/app/doi.org/[...doi]/page.tsx (2)
  • Page (73-103)
  • Props (18-22)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: test / cypress (4)
  • GitHub Check: test / cypress (3)
  • GitHub Check: test / cypress (5)
  • GitHub Check: test / cypress (1)
  • GitHub Check: test / cypress (2)
🔇 Additional comments (1)
src/app/doi.org/[...doi]/RelatedAggregateGraph.tsx (1)

13-13: LGTM! Clean implementation of embed support.

The addition of the isEmbed prop with a default value of false maintains backward compatibility while enabling the conditional layout adjustment for embedded contexts. The pattern mirrors the existing isBot prop approach consistently.

Also applies to: 39-39, 69-69

@@ -0,0 +1,18 @@
import React, { Suspense } from 'react';
import RelatedAggregateGraph from 'src/app//doi.org/[...doi]/RelatedAggregateGraph';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix import path typo.

The import path contains a double slash: src/app//doi.org/[...doi]/RelatedAggregateGraph (note the // after app).

Apply this diff:

-import RelatedAggregateGraph from 'src/app//doi.org/[...doi]/RelatedAggregateGraph';
+import RelatedAggregateGraph from 'src/app/doi.org/[...doi]/RelatedAggregateGraph';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import RelatedAggregateGraph from 'src/app//doi.org/[...doi]/RelatedAggregateGraph';
import RelatedAggregateGraph from 'src/app/doi.org/[...doi]/RelatedAggregateGraph';
🤖 Prompt for AI Agents
In src/app/(embed)/embed/related-aggregate/[...doi]/page.tsx around line 2, the
import path has a double slash
("src/app//doi.org/[...doi]/RelatedAggregateGraph"); fix it by correcting the
path to remove the extra slash so it imports from
"src/app/doi.org/[...doi]/RelatedAggregateGraph" (ensure the adjusted relative
path matches project structure and run a quick compile to verify).

Comment on lines +4 to +9
type Props = {
params: { doi: string[] }
};

export default function EmbedRelatedAggregateGraphPage({ params }: Props) {
const doi = params.doi.join('/');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

Verify params handling and add URL decoding.

Two concerns:

  1. Params type inconsistency: The main DOI page at src/app/doi.org/[...doi]/page.tsx (lines 17-21, 72-74) treats params as Promise<{ doi: string[] }> and awaits it, but this component treats it as synchronous. This could cause runtime errors depending on Next.js routing behavior.

  2. Missing URL decoding: The main page uses decodeURIComponent(params.doi.join('/')) (line 73), but this embed page omits decoding. DOIs with special characters (e.g., 10.1000/test%2Fpath) will break.

Run the following script to verify how params are handled in other dynamic routes:

Apply this diff if params should be async (recommended based on main page pattern):

-type Props = {
-  params: { doi: string[] }
+type Props = {
+  params: Promise<{ doi: string[] }>
 };

-export default function EmbedRelatedAggregateGraphPage({ params }: Props) {
-  const doi = params.doi.join('/');
+export default async function EmbedRelatedAggregateGraphPage({ params }: Props) {
+  const resolvedParams = await params;
+  const doi = decodeURIComponent(resolvedParams.doi.join('/'));

🏁 Script executed:

#!/bin/bash
# Check params handling patterns across dynamic routes
rg -n -A 3 'params.*Promise' --type=tsx --type=ts
rg -n -A 3 'decodeURIComponent.*params' --type=tsx --type=ts

Length of output: 55


🏁 Script executed:

#!/bin/bash
# Locate all page.tsx files under any `[...doi]` directory
echo "Found dynamic DOI page files:"
fd -t f -e tsx '\[\.\.\.doi\]' src/app

# For each file, inspect params handling and URL decoding
for f in $(fd -t f -e tsx '\[\.\.\.doi\]' src/app); do
  echo
  echo "----- $f -----"
  rg -n -C2 'export default (async )?function' --glob "$f"
  rg -n 'await params' --glob "$f"
  rg -n 'decodeURIComponent' --glob "$f"
done

Length of output: 29


🏁 Script executed:

#!/bin/bash
echo "Listing all .tsx files under src/app:"
fd -e tsx src/app

echo
echo "Filtering for '[...doi]' in paths:"
find src/app -type f -name '*.tsx' | grep '\[...doi\]'

echo
for f in $(find src/app -type f -name '*.tsx' | grep '\[...doi\]'); do
  echo
  echo "----- $f -----"
  head -n 20 "$f"
  echo "- Async export:"
  rg -n '^export default.*async' --glob "$f" || echo "  none"
  echo "- Await params:"
  rg -n 'await params' --glob "$f" || echo "  none"
  echo "- decodeURIComponent:"
  rg -n 'decodeURIComponent' --glob "$f" || echo "  none"
done

Length of output: 6743


🏁 Script executed:

#!/bin/bash
# Locate embed and main DOI page files
embed=$(find src/app -type f -path "*/(embed)/*/page.tsx")
main=$(find src/app -type f -path "*/doi.org/*/page.tsx" | grep '\[...doi\]/page.tsx')

echo "Embed file: $embed"
echo "Main file: $main"

echo
echo "----- EMBED PAGE ($embed) -----"
sed -n '1,200p' "$embed"

echo
echo "----- MAIN PAGE ($main) -----"
sed -n '1,200p' "$main"

Length of output: 3555


Decode DOI in embed page

In src/app/(embed)/embed/related-aggregate/[...doi]/page.tsx replace:

const doi = params.doi.join('/');

with

const doi = decodeURIComponent(params.doi.join('/'));
🤖 Prompt for AI Agents
In src/app/(embed)/embed/related-aggregate/[...doi]/page.tsx around lines 4 to
9, the DOI is being reconstructed from route params without decoding URL-encoded
characters; replace the current reconstruction with decoding by calling
decodeURIComponent on the joined params (i.e.,
decodeURIComponent(params.doi.join('/'))) so the DOI contains original
characters like slashes or percent-encoded segments.

Comment on lines +1 to +13
import React from 'react';

export default function EmbedLayout({ children }: { children: React.ReactNode }) {
return (
<html>
<body>
<div>
{children}
</div>
</body>
</html>
);
} No newline at end of file
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add proper HTML document structure for embed layout.

The layout is missing critical HTML elements that affect accessibility, SEO, and proper rendering:

  1. Missing lang attribute on <html> tag (accessibility requirement for screen readers)
  2. Missing <head> section with essential meta tags:
    • <meta charset="utf-8" />
    • <meta name="viewport" content="width=device-width, initial-scale=1" />
  3. No CSS classes or styling to ensure consistent rendering

Apply this diff to add proper HTML structure:

 import React from 'react';

 export default function EmbedLayout({ children }: { children: React.ReactNode }) {
   return (
-    <html>
+    <html lang="en">
+      <head>
+        <meta charSet="utf-8" />
+        <meta name="viewport" content="width=device-width, initial-scale=1" />
+      </head>
       <body>
-        <div>
-          {children}
-        </div>
+        {children}
       </body>
     </html>
   );
 }

Note: The extra <div> wrapper is unnecessary—{children} can be rendered directly in <body>.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import React from 'react';
export default function EmbedLayout({ children }: { children: React.ReactNode }) {
return (
<html>
<body>
<div>
{children}
</div>
</body>
</html>
);
}
import React from 'react';
export default function EmbedLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
{children}
</body>
</html>
);
}
🤖 Prompt for AI Agents
In src/app/(embed)/embed/related-aggregate/layout.tsx around lines 1-13, the
HTML document lacks a lang attribute, a head section with essential meta tags,
and unnecessary wrapper markup; modify the root html tag to include lang="en",
add a <head> containing <meta charSet="utf-8" /> and <meta name="viewport"
content="width=device-width, initial-scale=1" />, remove the extra <div> so
{children} is rendered directly inside <body>, and add a CSS class on <body>
(e.g., className="embed-root") so global or local styles can target this layout
for consistent rendering.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant