Skip to content

Remix stack glossary/fix - #874

Merged
jakeaturner merged 16 commits into
stagingfrom
remix-stack-glossary/fix
Jul 28, 2026
Merged

Remix stack glossary/fix#874
jakeaturner merged 16 commits into
stagingfrom
remix-stack-glossary/fix

Conversation

@yghaemi

@yghaemi yghaemi commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Multiple fixes based on Delamr's request.

@yghaemi
yghaemi requested a review from jakeaturner July 27, 2026 20:01
Comment thread server/util/librariesclient.ts Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR applies a set of server + client fixes around Remixer, Glossary import, and License Restacker behavior/UI, including new ordering/metadata-copy behavior in the Remixer job and expanded license compatibility/version handling.

Changes:

  • Add Remixer improvements: page ordering via CXOne order API (including “Back Matter last”), copy thumbnail/overview on import, and allow larger Remixer save/publish payloads via streamed JSON parsing.
  • Extend Glossary tooling: support importing terms from an auxiliary glossary page and broaden glossary lookups to match on ancestor cover IDs.
  • Update License Restacker logic/UI: refine compatibility matrix, add per-license version options, improve conflict presentation, and add bulk “Fix All” preview/apply flow.

Reviewed changes

Copilot reviewed 31 out of 31 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
server/util/Restackerutil.ts Adds retry wrapper around license/content-license retrieval during restacker processing.
server/util/librariesclient.ts Adds a reference comment for the MindTouch/CXOne page order API URL.
server/util/CXOne/CXOnePageAPIEndpoints.ts Adds a new ORDER_PAGES endpoint helper for the CXOne order API.
server/middleware.ts Introduces streamJsonBody to parse JSON request bodies without using Express’s global json parser.
server/api/validators/book.ts Extends glossary import validator with optional auxiliary glossary page IDs.
server/api/services/remixer-service.ts Adds back-matter detection + ordering, orders newly created/imported pages, and copies thumbnail/overview during import.
server/api/services/glossary-service.ts Refactors glossary extraction, adds auxiliary glossary import flow, and broadens glossary matching via ancestor cover IDs.
server/api/restacker.ts Updates license-compatibility/conflict logic and warning messaging, including book-wide checks.
server/api/books.ts Updates glossary import route handling to support auxiliary glossary imports and return extracted term data.
server/api.js Switches Remixer save/publish routes to middleware.streamJsonBody and removes debug logging middleware.
client/src/screens/commons/Glossary/TOCTreeView.tsx Adds persisted expand state + per-node “import glossary” action in the TOC tree.
client/src/screens/commons/Glossary/index.tsx Adds breadcrumb for project glossary view and wires auxiliary glossary import params to the mutation.
client/src/Conductor.jsx Changes the Remixer route to /projects/:id/remixer.
client/src/components/util/LicenseOptions.js Adds per-license version option lists and exports a helper to retrieve them.
client/src/components/remixer/services.ts Adjusts formatted-path override behavior to allow empty overrides and align display logic.
client/src/components/remixer/RemixerDashboard.tsx Adds breadcrumb and prevents “save with no changes” from marking nodes modified.
client/src/components/remixer/model.ts Updates copy mode titles (UI text adjustments).
client/src/components/remixer/EditPanel.tsx Improves focus behavior and keyboard navigation within the edit modal.
client/src/components/remixer/ControlPanel.tsx Improves layout/labels/tooltips and popup positioning for save/publish actions.
client/src/components/remixer/CatalogBook/CatalogList.tsx Adds a single-select checkbox column using the table’s selection column helper.
client/src/components/remixer/BookContent/TreeNodeContainer.tsx Adjusts link rendering/styling and keeps status icons outside the title span.
client/src/components/remixer/BookContent/Dashboard.tsx Reuses computed displayTitle and adjusts link/title rendering similarly to TreeNodeContainer.
client/src/components/projects/Restacker/util.ts Updates compatibility logic to incorporate versions and expands proposed-license compliance to support book-wide checks.
client/src/components/projects/Restacker/LicenseWarningModal.tsx Improves conflict display for book-wide conflicts and adds scrollable list styling.
client/src/components/projects/Restacker/LicenseEditor.tsx Uses per-license version options instead of a global version list; tightens UI styling.
client/src/components/projects/Restacker/LicenseBadge.tsx Improves badge sizing/layout for consistent rendering.
client/src/components/projects/Restacker/index.tsx Adds “Next Conflict” navigation and “Fix All” preview/apply flow; locks structural/source-mismatch cases and adds quick-apply.
client/src/components/projects/Restacker/FixAllPreviewModal.tsx New modal to preview bulk “Fix All” license changes before applying.
client/src/components/projects/Restacker/ComplianceDetails.tsx Aligns compliance UI with the renamed license pair structure.
client/src/components/projects/ProjectLinkButtons.tsx Updates the Remixer project link to the new /projects/:id/remixer route.
client/src/api.ts Adds a fetch-based JSON sender for remixer save/publish and extends glossary import payload shape.
Comments suppressed due to low confidence (1)

client/src/screens/commons/Glossary/TOCTreeView.tsx:122

  • IconDownload is clickable but marked aria-hidden and has no keyboard interaction. This hides the import action from assistive tech and prevents keyboard users from triggering it.
              className={`opacity-0 group-hover/node:opacity-100 transition-opacity shrink-0 text-info-500 ${
                importingGlossary ? "pointer-events-none opacity-40" : ""
              }`}
              aria-hidden
              onClick={(e: React.MouseEvent) => {

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread server/api/services/glossary-service.ts
Comment thread server/api/services/glossary-service.ts
Comment thread server/middleware.ts
Comment on lines +355 to +365
/**
* Reads the incoming request body as a Node.js readable stream — no size
* ceiling — then parses it as JSON and assigns the result to `req.body`.
*
* Use this instead of the global `bodyParser.json()` on routes that must
* accept arbitrarily large JSON payloads (e.g. remixer book-state save and
* publish). The calling route must be excluded from the global body-parser
* middleware so the stream is not consumed before this runs.
*/
const STREAM_JSON_MAX_BYTES = 5 * 1024 * 1024; // 10 MB

Comment on lines +309 to +313
* Moves Back Matter to the end of its sibling list via CXOne's page order API.
*
* PUT /pages/{lastSiblingId}/order?afterid={backMatterId}
* — path is the last page on the same level; afterid is the Back Matter page.
* @returns true when an order request was issued.
Comment on lines +38 to +40
const isTransientError = (error: unknown): boolean =>
error instanceof Error && error.message.includes("Transient error");

Comment thread client/src/components/remixer/EditPanel.tsx
Comment on lines +107 to +115
<IconExternalLink
size={20}
className="opacity-0 group-hover/node:opacity-100 transition-opacity shrink-0 text-info-500"
aria-hidden
onClick={(e: React.MouseEvent) => {
e.stopPropagation();
window.open(item.url, "_blank");
}}
/>
Comment thread client/src/api.ts
Comment on lines +125 to +133
/**
* Streams a JSON payload to the server using a `ReadableStream` fetch body.
* This bypasses Express's `bodyParser.json()` size ceiling — the server reads
* the body from the raw stream with no limit. Auth is handled by the session
* cookie (`credentials: "include"` mirrors `axios.defaults.withCredentials`).
*
* Returns the parsed JSON response, or throws with a shape compatible with
* the Axios error format so callers can handle it uniformly.
*/
Comment thread server/api/restacker.ts
Comment on lines +133 to 137
const ccKeyOrigin = toCcLicenseKey(keyOrigin);
if (!ccKeyAdption || !ccKeyOrigin) return null;

return CC_COMPATIBILITY_MATRIX[ccKeyA][ccKeyB];
return CC_COMPATIBILITY_MATRIX[ccKeyAdption][ccKeyOrigin];
}

@jakeaturner jakeaturner left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Sorry I didn't realize I was pushing to your branch!

Comment thread server/middleware.ts
res.status(400).json({ err: true, errMsg: "Invalid or malformed JSON body" });
}
});
req.on("error", () => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Need to add a check against trying to send a response if headers have already flushed --ERR_HTTP_HEADERS_SENT will get thrown and there's nothing outside that will catch it, causing a server crash.

Recommend something like this:

let finished = false;
const fail = (status: number, errMsg: string) => {
  if (finished) return;
  finished = true;
  req.pause();
  res.status(status).json({ err: true, errMsg });
};

Then call fail() in each catch block and req.on("error") instead of directly calling res.status(400).json....)

Comment thread server/api/services/glossary-service.ts
yghaemi added 16 commits July 28, 2026 09:26
… and publish

- Added a `streamJson` method to the API class to handle large JSON payloads without size limitations, bypassing Express's bodyParser.json() ceiling.
- Updated the remixer project save and publish methods to utilize the new streaming functionality for improved performance.
- Enhanced error handling to align with Axios error format for consistent response management.
- Refactored routes in the server to support streaming JSON for remixer operations, ensuring efficient data handling.
- Adjusted related components and routes to reflect updated API paths and improve user navigation.
- Implemented `isBackMatterNode` to identify Back Matter pages.
- Created `orderBackMatterLast` function to reorder Back Matter to the end of its siblings using CXOne's page order API.
- Updated `runRemixerJob` to ensure Back Matter is ordered last during job execution.
- Enhanced CXOnePageAPIEndpoints with a new `ORDER_PAGES` endpoint for ordering pages.
- Added a class for larger text size to links and spans in the TreeDnd component.
- Restored color styling for the link icon to maintain visual consistency.
- Adjusted styles to improve readability and user interaction experience.
- Refactored license handling in the Restacker component to improve compliance checks and user interactions.
- Introduced `areLicensesCompatible` utility for better license validation.
- Updated LicenseEditor to dynamically fetch license version options, enhancing user experience.
- Improved styling and layout of LicenseBadge for better visual consistency.
- Removed deprecated license version options and streamlined related functions for clarity and efficiency.
- Introduced new utility functions for improved license validation and compliance checks.
- Added functionality to automatically suggest license corrections for structural pages.
- Updated LicenseEditor and LicenseBadge components for better user interaction and visual consistency.
- Enhanced table column definitions for improved layout and responsiveness.
- Refactored existing functions to streamline license handling and improve code clarity.
…upport

- Updated API methods to include optional parameters for auxiliary glossary IDs and parent IDs.
- Modified the GlossaryManager component to handle new glossary import functionality.
- Enhanced TOCTreeView to support importing glossary terms with auxiliary references.
- Refactored glossary service methods to accommodate new logic for handling auxiliary glossaries.
- Improved validation schema to include new parameters for glossary usage.
- Refactored LicenseWarningModal to improve display of incompatible license pairs.
- Updated utility functions to change license structure from `licenseA` and `licenseB` to `licenseAdption` and `licenseOrigin`.
- Adjusted compatibility matrix to reflect accurate license relationships and compliance checks.
- Enhanced license version handling in utility functions for better validation.
- Updated ComplianceDetails component to reflect new license structure with `licenseAdption` and `licenseOrigin`.
- Enhanced LicenseWarningModal to conditionally display page titles based on the field type.
- Improved utility functions for better license version handling and compliance checks.
- Adjusted API compatibility logic to ensure accurate license relationship assessments.
…e handling

- Added a new method `withRetryOnTransient` to handle transient errors during license retrieval with incremental backoff.
- Updated license fetching logic in `runRestacker` to utilize the new retry mechanism, improving resilience against temporary failures.
…g page import

- Implemented a new method `copyPageThumbnailAndOverview` to copy the thumbnail image and overview from a source page to a target page.
- Enhanced error handling to log non-fatal errors during the copying process without aborting the import.
- Updated the `handleImportedPage` function to include the new thumbnail and overview copying logic.
…bling

- Added `orderPageAfterPreviousSibling` function to position newly created or imported pages correctly in relation to their siblings using the MindTouch page-order API.
- Integrated the new ordering logic into the `runRemixerJob` function to ensure pages are ordered appropriately during job execution.
- Enhanced error handling to log warnings for non-fatal errors during the ordering process, allowing the job to continue even if the ordering fails.
- Refactored logic in `resolveInheritedFormattedPathPrefix` and `getRemixerDisplayTitle` to streamline formatted path checks and ensure proper handling of empty strings.
- Updated `buildBookPaths` to improve clarity in formatted path assignment and override checks.
- Enhanced code readability by reducing redundant conditions and improving null handling for formatted paths.
…d UI

- Changed popup position from "bottom center" to "bottom right" for better alignment.
- Added offset and popper modifiers to prevent overflow and enhance visibility within the viewport.
- Ensured consistent styling and behavior for both "Save Remixing Map draft" and "Save Book to Library" popups.
…te ID handling

- Refactored `getGlossaryPage` and `getGlossaryDetails` methods to utilize a new helper function `getCandidateCoverIDs` for better handling of page IDs and their ancestors.
- Updated database queries to use candidate IDs for more accurate glossary retrieval.
- Enhanced error handling and code readability by simplifying conditional checks and improving variable naming conventions.
…e glossary management

- Updated parameter names from `augGlossaryParentID` to `auxGlossaryParentID` across multiple files for consistency.
- Adjusted API methods and components to ensure proper handling of auxiliary glossary IDs and parent IDs.
- Enhanced validation schema to reflect the corrected parameter naming, improving clarity and reducing potential errors.
- Introduced a maximum size limit of 5 MB for JSON request bodies in the streamJsonBody middleware.
- Added logic to destroy the request and return a 413 status with an error message if the limit is exceeded.
- Enhanced data handling by tracking total bytes received during the streaming process.
@jakeaturner
jakeaturner force-pushed the remix-stack-glossary/fix branch from b421c1a to 9fa3db7 Compare July 28, 2026 16:27
@jakeaturner
jakeaturner merged commit b5738a0 into staging Jul 28, 2026
4 checks passed
@jakeaturner
jakeaturner deleted the remix-stack-glossary/fix branch July 28, 2026 16:28
@libretexts-bot

Copy link
Copy Markdown
Collaborator

🎉 This PR is included in version 2.140.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants