Skip to content

Commit 918d097

Browse files
authored
Document versions (#5610)
1 parent 062b1fb commit 918d097

111 files changed

Lines changed: 23626 additions & 333 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@apostrophecms/db-connect": patch
3+
---
4+
5+
The postgres cursor returns its pooled connection when iteration stops early: on a query error inside `next()`, and when a `for await` loop exits through `break`, `return` or a throwing body. Previously each abandoned cursor kept a connection checked out for the life of the process (PRO-10051).

‎.changeset/db-connect-ejson.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@apostrophecms/db-connect": patch
3+
---
4+
5+
Export the driver's `EJSON` (Extended JSON) so apostrophe modules can serialize documents without a direct driver dependency.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@apostrophecms/db-connect": patch
3+
---
4+
5+
The postgres adapter's `sort()` orders numbers numerically instead of as text, so `10` no longer sorts before `2` and the children of a page with ten or more of them stay in rank order (PRO-10055).

‎.changeset/document-versions.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"apostrophe": minor
3+
---
4+
5+
Document Versions ships in core as `@apostrophecms/document-versions`, on for pages and pieces by default and set per type with the `versions` option: a history of drafts and publications with the editor who saved each one and whether AI was involved, a list of what every version changed field by field, those changes marked on the document where they render, restore from a version's own entry, and Undo Publish through the history. Existing version records are converted on upgrade.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@apostrophecms/import-export": patch
3+
---
4+
5+
Documents translated during an import are recorded as AI-assisted versions in Document Versions.

‎.changeset/migration-each-close.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"apostrophe": patch
3+
---
4+
5+
`apos.migration.each` now closes its cursor when the iterator throws, instead of leaving it open (PRO-10051).

‎.github/workflows/monorepo.yml‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ on:
3434
required: false
3535
type: boolean
3636
default: false
37+
automatic-translation-ref:
38+
description: automatic-translation branch, tag or commit for the import-export tests with Pro modules
39+
required: false
40+
type: string
3741

3842
jobs:
3943
setup:
@@ -335,6 +339,7 @@ jobs:
335339
# Yes we want import-export to test with automatic-translation,
336340
# but only when the deploy key is available (not on fork PRs).
337341
TEST_WITH_PRO: ${{ env.HAS_PRO_KEY == 'true' && '1' || '' }}
342+
APOS_AUTOMATIC_TRANSLATION_REF: ${{ inputs.automatic-translation-ref || env.APOS_AUTOMATIC_TRANSLATION_REF }}
338343
# Adapter selection: mongodb (default), postgres, or sqlite.
339344
# ADAPTER is used by db-connect tests, APOS_TEST_DB_PROTOCOL by apostrophe tests.
340345
ADAPTER: ${{ matrix.adapter }}

‎packages/apostrophe/defaults.js‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ module.exports = {
6868
'@apostrophecms/submitted-draft': {},
6969
'@apostrophecms/recently-edited': {},
7070
'@apostrophecms/command-menu': {},
71-
'@apostrophecms/translation': {}
71+
'@apostrophecms/translation': {},
72+
'@apostrophecms/document-versions': {}
7273
}
7374
};

‎packages/apostrophe/modules/@apostrophecms/area/index.js‎

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,17 +121,43 @@ module.exports = {
121121
return 'aposLivePreviewSchemaNotYetValid';
122122
}
123123

124+
// A widget of a document version, posted with the widget it was
125+
// in the version before, hands it to its template when its type
126+
// sets `versionsRender`
127+
const older = await getOlderVersion();
128+
124129
widget._edit = true;
125130
widget._docId = _docId;
126131
// So that carrying out relationship loading again can yield results
127132
// (the idsStorage must be populated as if we were saving)
128133
self.apos.schema.prepareForStorage(req, widget);
134+
if (older) {
135+
self.apos.schema.prepareForStorage(req, older);
136+
}
129137
await load();
138+
if (older) {
139+
widget._olderVersion = older;
140+
}
130141
return render();
142+
async function getOlderVersion() {
143+
const data = req.body.widget?._olderVersion;
144+
if (!data || (typeof data !== 'object') || !manager.options.versionsRender) {
145+
return null;
146+
}
147+
try {
148+
return await manager.sanitize(req, data, options);
149+
} catch (e) {
150+
// It renders as it would without its older version
151+
return null;
152+
}
153+
}
131154
async function load() {
132155
// Hint to call nested widget loaders as if it were a doc
133156
widget._virtual = true;
134-
return manager.loadIfSuitable(req, [ widget ]);
157+
if (older) {
158+
older._virtual = true;
159+
}
160+
return manager.loadIfSuitable(req, older ? [ widget, older ] : [ widget ]);
135161
}
136162
async function render() {
137163
if (req.aposExternalFront) {

‎packages/apostrophe/modules/@apostrophecms/area/ui/apos/apps/AposAreas.js‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,10 @@ export default function() {
172172
event.claim();
173173
}
174174

175+
// The newest entry: a scroll right after `observe` arrives in the same
176+
// callback as the first report, which still says the area is out of view
175177
function observed(entries) {
176-
const intersects = entries[0].isIntersecting;
178+
const intersects = entries.at(-1).isIntersecting;
177179
if (!intersects) {
178180
return;
179181
}

0 commit comments

Comments
 (0)