Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
c0197c1
fix(remixer): correct label for formattedPathOverride checkbox
yghaemi Aug 26, 2026
beec9c2
refactor(remixer): enhance API and UI for handling published dates an…
yghaemi Aug 26, 2026
80b69c3
fix(remixer): adjust modal styling and table height in CatalogList co…
yghaemi Aug 26, 2026
a09f57b
refactor(remixer): streamline link rendering logic in Dashboard and T…
yghaemi Aug 26, 2026
1fbe9eb
style(remixer): enhance PublishPanel layout and styling
yghaemi Aug 26, 2026
affb102
feat(remixer): add isBookRootChild prop to TreeNodeContainer and upda…
yghaemi Aug 26, 2026
51b8a18
style(remixer): update LibraryActions component for improved layout a…
yghaemi Aug 26, 2026
71a9b06
refactor(remixer): update getBookPageIDs and related methods to skip …
yghaemi Aug 27, 2026
9f07475
style(remixer): improve code formatting and readability in RemixerDas…
yghaemi Aug 27, 2026
6628c0d
style(remixer): update ControlPanel icons and improve layout for bett…
yghaemi Aug 27, 2026
4b60e49
refactor(remixer): enhance RecoveryModal with recent source resolutio…
yghaemi Aug 27, 2026
ddeb4fa
refactor(remixer): optimize loadSelectedBook function for improved da…
yghaemi Aug 27, 2026
d0957c0
refactor(remixer): separate delete and non-delete entry processing in…
yghaemi Aug 27, 2026
4599ee5
refactor(remixer): improve book node deletion logic to handle draft-o…
yghaemi Aug 27, 2026
27798ee
style(remixer): adjust selectClassName padding in ControlPanel for im…
yghaemi Aug 27, 2026
8466383
refactor(remixer): enhance page handling with new options for title a…
yghaemi Aug 27, 2026
90147bc
refactor(remixer): update remixer tree fetching to include new option…
yghaemi Aug 28, 2026
40664eb
feat(remixer): implement file handling capabilities in BookService an…
yghaemi Aug 28, 2026
07fe859
refactor(remixer): update book ownership validation to support real-t…
yghaemi Aug 28, 2026
f6913e0
refactor(remixer): simplify REMIXER_PAGE_CONFIG_KEYS by removing unus…
yghaemi Aug 28, 2026
af4581a
refactor(remixer): update REMIXER_PAGE_CONFIG_KEYS and add conditiona…
yghaemi Aug 28, 2026
78c0816
refactor(remixer): update REMIXER_PAGE_CONFIG_KEYS to streamline conf…
yghaemi Aug 28, 2026
adcd8f6
feat(remixer): implement catalog node highlighting in library tree
yghaemi Aug 31, 2026
56f5e2a
fix(remixer): update publish button behavior and modal state management
yghaemi Aug 31, 2026
e0817c8
feat(remixer): add restore functionality for deleted book nodes
yghaemi Aug 31, 2026
2adb302
feat(remixer): enhance EditPanel and RemixerDashboard with URI ending…
yghaemi Sep 1, 2026
b648404
feat(remixer): enhance article kind handling during page import and r…
yghaemi Sep 1, 2026
2035660
feat(remixer): enhance EditPanel and RemixerDashboard with improved n…
yghaemi Sep 1, 2026
a8f1d93
feat(remixer): improve EditPanel URI handling and enhance RemixerDash…
yghaemi Sep 1, 2026
0b31149
feat(remixer): enhance EditPanel and model with improved URI handling…
yghaemi Sep 1, 2026
fc4362b
feat(remixer): implement joinPrefixAndIndex utility for improved path…
yghaemi Sep 1, 2026
7b7aed9
fix(remixer): correct import page id, override drift, delete 404s
jakeaturner Sep 2, 2026
145f800
fix(remixer): url override encoding, publish job recovery, state resets
jakeaturner Sep 2, 2026
8417ac6
fix(remixer): gate article-kind writes, persist restore flag, cap fil…
jakeaturner Sep 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 28 additions & 11 deletions client/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,12 @@ import {
EditAcademyOnlineAccessFormValues,
CentralIdentityUserLicenseResult,
CentralIdentityAppLicense,
StoreDigitalDeliveryOption, StoreOrderWithStripeSession, StoreOrderListItem,
ManualPrintJobPayload, ManualPrintJobPayloadResponse, ResubmitPrintJobRefusal,
StoreDigitalDeliveryOption,
StoreOrderWithStripeSession,
StoreOrderListItem,
ManualPrintJobPayload,
ManualPrintJobPayloadResponse,
ResubmitPrintJobRefusal,
OrderCharge,
OrderSession,
CentralIdentityOrgAdminResult,
Expand Down Expand Up @@ -819,11 +823,11 @@ class API {

async adminSubmitManualPrintJob(
order_id: string,
payload: ManualPrintJobPayload
payload: ManualPrintJobPayload,
) {
const res = await axios.post<{ data: unknown } & ConductorBaseResponse>(
`/store/admin/orders/${order_id}/print-job`,
payload
payload,
);
return res;
}
Expand Down Expand Up @@ -2841,11 +2845,18 @@ class API {
return res.data;
}

async createMatter(projectID: string, type: CreateMatterSelection, overwrite: boolean) {
const res = await axios.post<ConductorBaseResponse>(`/remixer/${projectID}/create-matter`, {
type,
overwrite,
});
async createMatter(
projectID: string,
type: CreateMatterSelection,
overwrite: boolean,
) {
const res = await axios.post<ConductorBaseResponse>(
`/remixer/${projectID}/create-matter`,
{
type,
overwrite,
},
);
return res.data;
}

Expand Down Expand Up @@ -2929,6 +2940,7 @@ class API {
reparented?: unknown[];
/** False when the live TOC was unavailable, so `untracked` proves nothing. */
reconciled?: boolean;
publishedAt?: Date | string;
} & ConductorBaseResponse
>(`/remixer/${id}/project`, {});
return res.data;
Expand Down Expand Up @@ -2962,11 +2974,16 @@ class API {
return res.data;
}

async getRemixerTreeFlattened(id: string, path: string, subdomain: string) {
async getRemixerTreeFlattened(
id: string,
path: string,
subdomain: string,
options?: { flatten?: boolean | true; preserveConfigs?: boolean | true },
) {
const res = await axios.post(`/remixer/${id}/page/tree`, {
path,
subdomain,
flatten: true,
options,
});
return res.data;
}
Expand Down
14 changes: 13 additions & 1 deletion client/src/components/remixer/BookActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
IconArrowForwardUp,
IconPlus,
IconTrash,
IconRestore,
IconChevronUp,
IconChevronDown,
} from "@tabler/icons-react";
Expand All @@ -16,6 +17,8 @@ interface BookActionsProps {
isNarrowScreen: boolean;
onAddItem: () => void;
onDeleteItem: () => void;
onRestoreItem: () => void;
isSelectedItemDeleted: boolean;
onUndo: () => void;
onRedo: () => void;
isAllExpanded: boolean;
Expand All @@ -36,6 +39,8 @@ const BookActions: React.FC<BookActionsProps> = ({
isNarrowScreen,
onAddItem,
onDeleteItem,
onRestoreItem,
isSelectedItemDeleted,
onUndo,
onRedo,
isAllExpanded,
Expand All @@ -53,7 +58,14 @@ const BookActions: React.FC<BookActionsProps> = ({
onAddItem();
}
},
{
isSelectedItemDeleted ? {
title: "Restore",
icon: <IconRestore size={18} />,
variant: "outline",
onClick: () => {
onRestoreItem();
}
} : {
title: "Delete",
icon: <IconTrash size={18} />,
variant: "destructive",
Expand Down
30 changes: 22 additions & 8 deletions client/src/components/remixer/BookContent/ContextMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ type ContextMenuAction =
| "add-below"
| "add-to"
| "delete"
| "restore"
| "modify"
| "duplicate";

interface ContextMenuProps {
contextMenu: ContextMenuPosition | null;
canAddSibling: boolean;
canDuplicate: boolean;
isDeleted: boolean;
addAboveLabel: string;
addToLabel: string;
addBelowLabel: string;
Expand All @@ -37,6 +39,7 @@ const ContextMenu: React.FC<ContextMenuProps> = ({
contextMenu,
canAddSibling,
canDuplicate,
isDeleted,
addAboveLabel,
addToLabel,
addBelowLabel,
Expand Down Expand Up @@ -104,14 +107,25 @@ const ContextMenu: React.FC<ContextMenuProps> = ({
margin: "4px 0",
}}
/>
<div
style={itemStyle}
onMouseEnter={(e) => (e.currentTarget.style.background = "#f0f0f0")}
onMouseLeave={(e) => (e.currentTarget.style.background = "transparent")}
onClick={() => onAction("delete")}
>
<Icon name="trash alternate" /> Delete
</div>
{isDeleted ? (
<div
style={itemStyle}
onMouseEnter={(e) => (e.currentTarget.style.background = "#f0f0f0")}
onMouseLeave={(e) => (e.currentTarget.style.background = "transparent")}
onClick={() => onAction("restore")}
>
<Icon name="undo" /> Restore
</div>
) : (
<div
style={itemStyle}
onMouseEnter={(e) => (e.currentTarget.style.background = "#f0f0f0")}
onMouseLeave={(e) => (e.currentTarget.style.background = "transparent")}
onClick={() => onAction("delete")}
>
<Icon name="trash alternate" /> Delete
</div>
)}
<div
style={itemStyle}
onMouseEnter={(e) => (e.currentTarget.style.background = "#f0f0f0")}
Expand Down
108 changes: 73 additions & 35 deletions client/src/components/remixer/BookContent/Dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
sortMatterSiblings,
} from "../services";
import TreeNodeContainer from "./TreeNodeContainer";
import { STATUS_PALETTE } from "../style";
import { CATALOG_NODE_HIGHLIGHT_STYLE, STATUS_PALETTE } from "../style";

type DropPosition = "before" | "inside" | "after";
type TreeId = "library" | "book";
Expand Down Expand Up @@ -504,6 +504,7 @@ const TreeDnd: React.FC<TreeDndProps> = ({
const isPlacementChanged =
page.isPlacementChanged ?? page.movedItem === true;
const isSelected = selectedNodeId === page["@id"];
const isCatalogHighlighted = !isBookTree && isSelected;
const itemLink = page["uri.ui"] || page["@href"];
const isInteractionLocked = isDefaultMatterPage(page);
const isDropInside =
Expand All @@ -526,7 +527,9 @@ const TreeDnd: React.FC<TreeDndProps> = ({
isRenamed={isRenamed}
isPlacementChanged={isPlacementChanged}
isSelected={isSelected}
isCatalogHighlighted={isCatalogHighlighted}
isBookTree={isBookTree}
isBookRootChild={isBookTree && depth === 1}
isInteractionLocked={isInteractionLocked}
isVisualLocked={isInteractionLocked}
itemLink={itemLink}
Expand Down Expand Up @@ -604,6 +607,7 @@ const TreeDnd: React.FC<TreeDndProps> = ({
const isPlacementChanged =
root.isPlacementChanged ?? root.movedItem === true;
const isSelected = selectedNodeId === root["@id"];
const isCatalogHighlighted = !isBookTree && isSelected;
const itemLink = root["uri.ui"] || root["@href"];
const targetLevel = 1;
const isInteractionLocked = isDefaultMatterPage(root);
Expand All @@ -619,7 +623,11 @@ const TreeDnd: React.FC<TreeDndProps> = ({
);

return (
<div key={root["@id"]} data-node-id={root["@id"]}>
<div
key={root["@id"]}
data-node-id={root["@id"]}
style={isCatalogHighlighted ? CATALOG_NODE_HIGHLIGHT_STYLE : undefined}
>
<List.Item
draggable={!isInteractionLocked}
onDragStart={(event: DragEvent<HTMLDivElement>) => {
Expand Down Expand Up @@ -766,39 +774,69 @@ const TreeDnd: React.FC<TreeDndProps> = ({
<span style={{ width: 12 }} />

<Icon name="folder" color="grey" />
{!isBookTree && itemLink ? (
<a
href={itemLink}
target="_blank"
rel="noreferrer"
className="text-base"
style={{
whiteSpace: "nowrap",
fontStyle: isInteractionLocked ? "italic" : "normal",

textDecoration: isDeleted ? "line-through" : "none",
}}
onClick={(event) => event.stopPropagation()}
>
{displayTitle}
<Icon
name="linkify"
style={{ marginLeft: 8, color: "#1e70bf" }}
/>
</a>
) : (
<span
className="text-base"
style={{
whiteSpace: "nowrap",
fontStyle: isInteractionLocked ? "italic" : "normal",
color: isInteractionLocked ? "#6b7280" : "inherit",
textDecoration: isDeleted ? "line-through" : "none",
}}
>
{displayTitle}
</span>
)}
{(() => {
const showLink =
Boolean(itemLink) &&
itemLink !== "#" &&
(!isBookTree || !isImported);
const titleStyle: React.CSSProperties = {
whiteSpace: "nowrap",
fontStyle: isInteractionLocked ? "italic" : "normal",
color: isInteractionLocked ? "#6b7280" : "inherit",
textDecoration: isDeleted ? "line-through" : "none",
};

if (!showLink) {
return (
<span className="text-base" style={titleStyle}>
{displayTitle}
</span>
);
}

if (!isBookTree) {
return (
<a
href={itemLink}
target="_blank"
rel="noreferrer"
className="text-base"
style={{
...titleStyle,
color: undefined,
}}
onClick={(event) => event.stopPropagation()}
>
{displayTitle}
<Icon
name="linkify"
style={{ marginLeft: 8, color: "#1e70bf" }}
/>
</a>
);
}

return (
<>
<span className="text-base" style={titleStyle}>
{displayTitle}
</span>
<a
href={itemLink}
target="_blank"
rel="noreferrer"
title="Open page"
onClick={(event) => event.stopPropagation()}
style={{ display: "inline-flex", marginLeft: 8 }}
>
<Icon
name="linkify"
style={{ color: "#1e70bf", margin: 0 }}
/>
</a>
</>
);
})()}
</List.Item>
{renderNodes(
root["@id"],
Expand Down
Loading
Loading