Skip to content

PRO-8546: template page not found, various issues with the page tree and published pages - #5166

Merged
boutell merged 5 commits into
mainfrom
pro-8546
Nov 20, 2025
Merged

boutell merged 5 commits into
mainfrom
pro-8546

Conversation

@boutell

@boutell boutell commented Nov 20, 2025

Copy link
Copy Markdown
Member

No description provided.

@boutell
boutell requested a review from ValJed November 20, 2025 16:56
@linear

linear Bot commented Nov 20, 2025

Copy link
Copy Markdown

if (published && (doc.level > 0)) {
const { lastTargetId, lastPosition } = await self.apos.page
.inferLastTargetIdAndPosition(doc);
.inferLastTargetIdAndPosition(doc, { publishedTargetsOnly: true });

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Page tree editing occurs in draft, but we replay the movement afterwards in the published locale. When doing so we need to make sure we only look at published targets.

if (doc.level > 0) {
const { lastTargetId, lastPosition } = await self.apos.page
.inferLastTargetIdAndPosition(doc);
.inferLastTargetIdAndPosition(doc, { publishedTargetsOnly: true });

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Similarly, insertPublishedOf should only look at published targets.

// Insert a page. `targetId` must be an existing page id, `_archive` or
// `_home`, and `position` may be `before`, `inside` or `after`.
// Alternatively `position` may be a zero-based offset for the new child
// `_home`, and `position` may be `before`, `after`, `firstChild` or `lastChild`.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Unrelated correction to the documentation.

if (publishedTargetsOnly) {
const parent = await self.apos.doc.db.findOne({ _id: parentId });
if (!parent?.lastPublishedAt) {
throw self.apos.error('notfound');

@boutell boutell Nov 20, 2025 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We have a strict policy against publishing children of unpublished parents and the UI enforces that etc., so all we need to do is sanity check here. It works out for doc template library because doc templates are children of the home page, and parked pages are always published.

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.

Yup makes sense.

lastPublishedAt: 1
}).toArray();
const peers = publishedTargetsOnly
? allPeers.filter(peer => (peer._id === doc._id) || peer.lastPublishedAt)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We're working with drafts, but consider only those that have a published equivalent (and the page in question itself, that information is used to determine relative ranks).

position = 'after';
}
if (publishedTargetsOnly) {
targetId = targetId.replace(':draft', ':published');

@boutell boutell Nov 20, 2025 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Return a published target id.

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.

Clearer, the inferIdLocaleAndMode also does that, it also mutates req which is hard to debug.
I prefer to do it here, not sure we can get rig of inferIdLocaleAndMode in getTarget.`

Comment thread test/pages.js

// Publish and assert.
// Obviously, should not throw an error.
// Publish them in reverse order, then verify the published ranks

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I updated these tests a lot for correctness and maintainability / readability.

Comment thread test/pages.js
path: `${home.aposDocId}/${level1Page2.aposDocId}`,
level: 1,
rank: 4,
rank: 3,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I went through this and determined that these new relative ranks are correct. It's just that the new code leaves fewer gaps between ranks.

Comment thread test/pages.js
});
});

// We do not support autopublished page types per se, especially

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Here is my version of your new test, plus a comment for posterity to explain why we have it.

Comment thread test/pages.js
});
});

function getIndexes(all, mode, pages) {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Utility to reduce boilerplate and return an object with named properties for more readable tests.

@ValJed ValJed 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.

Seem a legit workaround if we do not face issues with this diff between draft and published trees. If we publish a draft page, will it move pages around too?

Just style feedback and a concern about parentId that can be an _id or an aposDocId.

if (publishedTargetsOnly) {
const parent = await self.apos.doc.db.findOne({ _id: parentId });
if (!parent?.lastPublishedAt) {
throw self.apos.error('notfound');

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.

Yup makes sense.

? `${parentAposDocId}:${doc.aposLocale}`
: parentAposDocId;
if (publishedTargetsOnly) {
const parent = await self.apos.doc.db.findOne({ _id: parentId });

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.

Looks like parentId can also be an aposDocId if doc has no aposLocale, it might happen only on a non localized site? I still don't think this request would be valid.
Also, are we sure it will request the draft version of the parent? It's ok if we're sure doc is always draft.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

aposDocId and _id are equal for a non localized page so this would not fail in that situation.

}).toArray();
const peers = publishedTargetsOnly
? allPeers.filter(peer => (peer._id === doc._id) || peer.lastPublishedAt)
: allPeers;

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.

Don't think you need more data in the projection, same for the filter filter here:

        const peerCriteria = {
          path: self.matchDescendants(parentPath),
          level: doc.level,
          ...doc.aposLocale && { aposLocale: doc.aposLocale },
          ...publishedTargetsOnly && { lastPublishedAt: { $ne: null } }
        };
        const peers = await self.apos.doc.db
          .find(peerCriteria)
          .sort({ rank: 1 })
          .project({ _id: 1 })
          .toArray();

position = 'after';
}
if (publishedTargetsOnly) {
targetId = targetId.replace(':draft', ':published');

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.

Clearer, the inferIdLocaleAndMode also does that, it also mutates req which is hard to debug.
I prefer to do it here, not sure we can get rig of inferIdLocaleAndMode in getTarget.`

@boutell
boutell requested a review from ValJed November 20, 2025 18:15
@boutell
boutell merged commit 0761b1f into main Nov 20, 2025
12 of 21 checks passed
@boutell
boutell deleted the pro-8546 branch November 20, 2025 21:40
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.

2 participants