@a3s-lab/office 0.7.3 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/COLLABORATION_ROADMAP.md +54 -27
- package/README.md +13 -1
- package/dist/0~document-editor.js +115 -43
- package/dist/8928.js +395 -23
- package/dist/9787.js +3 -2
- package/dist/core.d.ts +1 -1
- package/dist/internal/collaboration/office-collaboration.d.ts +1 -1
- package/dist/internal/collaboration/office-document-collaboration-change-decisions.d.ts +7 -0
- package/dist/internal/collaboration/office-document-collaboration-claims.d.ts +2 -1
- package/dist/internal/collaboration/office-document-collaboration-sidecars.d.ts +3 -1
- package/dist/internal/collaboration/office-document-collaboration-suggestions.d.ts +6 -0
- package/dist/internal/collaboration/office-document-collaboration.d.ts +6 -2
- package/dist/internal/features/work/editors/document-changes-panel.d.ts +7 -1
- package/dist/internal/features/work/editors/document-toolbar.d.ts +4 -1
- package/dist/internal/features/work/work-document-changes.d.ts +5 -2
- package/dist/internal/features/work/work-document-extensions.d.ts +1 -0
- package/dist/internal/features/work/work-document-paragraph-identity.d.ts +1 -0
- package/dist/internal/features/work/work-document-table-row-identity.d.ts +5 -1
- package/dist/internal/features/work/work-types.d.ts +20 -0
- package/dist/office-kernel.wasm +0 -0
- package/dist/styles.css +65 -0
- package/package.json +5 -3
package/dist/8928.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Extension, Mark, Node as core_Node, ResizableNodeView, generateHTML, getSchema, mergeAttributes } from "@tiptap/core";
|
|
2
2
|
import { Collaboration, isChangeOrigin } from "@tiptap/extension-collaboration";
|
|
3
3
|
import { NodeSelection, Plugin, PluginKey, TextSelection } from "@tiptap/pm/state";
|
|
4
|
-
import { AddMarkStep, Mapping, RemoveMarkStep } from "@tiptap/pm/transform";
|
|
4
|
+
import { AddMarkStep, Mapping, RemoveMarkStep, ReplaceStep } from "@tiptap/pm/transform";
|
|
5
5
|
import { defaultDeleteFilter, defaultProtectedNodes, prosemirrorJSONToYXmlFragment, ySyncPluginKey, yXmlFragmentToProsemirrorJSON } from "@tiptap/y-tiptap";
|
|
6
6
|
import extension_color from "@tiptap/extension-color";
|
|
7
7
|
import { Table, TableCell, TableHeader, TableKit, TableRow, TableView, createTable } from "@tiptap/extension-table";
|
|
@@ -6697,6 +6697,7 @@ const DocumentParagraphIdentity = Extension.create({
|
|
|
6697
6697
|
name: 'documentParagraphIdentity',
|
|
6698
6698
|
addOptions () {
|
|
6699
6699
|
return {
|
|
6700
|
+
rotateTextId: ()=>true,
|
|
6700
6701
|
types: [
|
|
6701
6702
|
'paragraph',
|
|
6702
6703
|
'heading',
|
|
@@ -6735,7 +6736,7 @@ const DocumentParagraphIdentity = Extension.create({
|
|
|
6735
6736
|
},
|
|
6736
6737
|
addProseMirrorPlugins () {
|
|
6737
6738
|
return [
|
|
6738
|
-
createDocumentParagraphIdentityPlugin(this.options.types)
|
|
6739
|
+
createDocumentParagraphIdentityPlugin(this.options.types, this.options.rotateTextId)
|
|
6739
6740
|
];
|
|
6740
6741
|
}
|
|
6741
6742
|
});
|
|
@@ -6776,11 +6777,11 @@ function applyDocumentParagraphIdentityToElement(element, source) {
|
|
|
6776
6777
|
element.setAttribute(DOCUMENT_PARAGRAPH_TEXT_ID_ATTRIBUTE, identity.textId);
|
|
6777
6778
|
return identity;
|
|
6778
6779
|
}
|
|
6779
|
-
function createDocumentParagraphIdentityPlugin(types) {
|
|
6780
|
+
function createDocumentParagraphIdentityPlugin(types, rotateTextId) {
|
|
6780
6781
|
const trackedTypes = new Set(types);
|
|
6781
6782
|
return new Plugin({
|
|
6782
6783
|
view (view) {
|
|
6783
|
-
const transaction = normalizeDocumentParagraphIdentities(view.state, trackedTypes);
|
|
6784
|
+
const transaction = normalizeDocumentParagraphIdentities(view.state, trackedTypes, rotateTextId);
|
|
6784
6785
|
if (transaction) {
|
|
6785
6786
|
transaction.setMeta('addToHistory', false);
|
|
6786
6787
|
view.dispatch(transaction);
|
|
@@ -6789,16 +6790,16 @@ function createDocumentParagraphIdentityPlugin(types) {
|
|
|
6789
6790
|
},
|
|
6790
6791
|
appendTransaction (transactions, oldState, newState) {
|
|
6791
6792
|
if (!transactions.some((transaction)=>transaction.docChanged)) return null;
|
|
6792
|
-
return normalizeDocumentParagraphIdentities(newState, trackedTypes, oldState, transactions);
|
|
6793
|
+
return normalizeDocumentParagraphIdentities(newState, trackedTypes, rotateTextId, oldState, transactions);
|
|
6793
6794
|
}
|
|
6794
6795
|
});
|
|
6795
6796
|
}
|
|
6796
|
-
function normalizeDocumentParagraphIdentities(state, trackedTypes, oldState, transactions = []) {
|
|
6797
|
+
function normalizeDocumentParagraphIdentities(state, trackedTypes, rotateTextId, oldState, transactions = []) {
|
|
6797
6798
|
const paragraphs = documentParagraphs(state.doc, trackedTypes);
|
|
6798
6799
|
const identifiedParagraphs = paragraphs.filter(({ node })=>hasDocumentParagraphIdentityComponent(node));
|
|
6799
6800
|
if (!identifiedParagraphs.length) return null;
|
|
6800
6801
|
const retainedPositions = oldState ? retainedDocumentParagraphPositions(oldState, state, transactions, trackedTypes) : new Set();
|
|
6801
|
-
const editedPositions = oldState && !transactions.some(isHistoryTransaction) ? editedDocumentParagraphPositions(oldState, state, transactions, trackedTypes) : new Set();
|
|
6802
|
+
const editedPositions = oldState && rotateTextId() && !transactions.some(isHistoryTransaction) ? editedDocumentParagraphPositions(oldState, state, transactions, trackedTypes) : new Set();
|
|
6802
6803
|
const ordered = [
|
|
6803
6804
|
...identifiedParagraphs.filter((item)=>retainedPositions.has(item.position)),
|
|
6804
6805
|
...identifiedParagraphs.filter((item)=>!retainedPositions.has(item.position))
|
|
@@ -6971,6 +6972,11 @@ const DOCUMENT_TABLE_ROW_ID_ATTRIBUTE = 'data-office-row-id';
|
|
|
6971
6972
|
const DOCUMENT_TABLE_ROW_TEXT_ID_ATTRIBUTE = 'data-office-row-text-id';
|
|
6972
6973
|
const DocumentTableRowIdentity = Extension.create({
|
|
6973
6974
|
name: 'documentTableRowIdentity',
|
|
6975
|
+
addOptions () {
|
|
6976
|
+
return {
|
|
6977
|
+
rotateTextId: ()=>true
|
|
6978
|
+
};
|
|
6979
|
+
},
|
|
6974
6980
|
addGlobalAttributes () {
|
|
6975
6981
|
return [
|
|
6976
6982
|
{
|
|
@@ -6986,7 +6992,7 @@ const DocumentTableRowIdentity = Extension.create({
|
|
|
6986
6992
|
},
|
|
6987
6993
|
addProseMirrorPlugins () {
|
|
6988
6994
|
return [
|
|
6989
|
-
createDocumentTableRowIdentityPlugin()
|
|
6995
|
+
createDocumentTableRowIdentityPlugin(this.options.rotateTextId)
|
|
6990
6996
|
];
|
|
6991
6997
|
}
|
|
6992
6998
|
});
|
|
@@ -7028,10 +7034,10 @@ function identityAttribute(htmlName) {
|
|
|
7028
7034
|
}
|
|
7029
7035
|
};
|
|
7030
7036
|
}
|
|
7031
|
-
function createDocumentTableRowIdentityPlugin() {
|
|
7037
|
+
function createDocumentTableRowIdentityPlugin(rotateTextId) {
|
|
7032
7038
|
return new Plugin({
|
|
7033
7039
|
view (view) {
|
|
7034
|
-
const transaction = normalizeDocumentTableRowIdentities(view.state);
|
|
7040
|
+
const transaction = normalizeDocumentTableRowIdentities(view.state, rotateTextId);
|
|
7035
7041
|
if (transaction) {
|
|
7036
7042
|
transaction.setMeta('addToHistory', false);
|
|
7037
7043
|
view.dispatch(transaction);
|
|
@@ -7040,16 +7046,16 @@ function createDocumentTableRowIdentityPlugin() {
|
|
|
7040
7046
|
},
|
|
7041
7047
|
appendTransaction (transactions, oldState, newState) {
|
|
7042
7048
|
if (!transactions.some((transaction)=>transaction.docChanged)) return null;
|
|
7043
|
-
return normalizeDocumentTableRowIdentities(newState, oldState, transactions);
|
|
7049
|
+
return normalizeDocumentTableRowIdentities(newState, rotateTextId, oldState, transactions);
|
|
7044
7050
|
}
|
|
7045
7051
|
});
|
|
7046
7052
|
}
|
|
7047
|
-
function normalizeDocumentTableRowIdentities(state, oldState, transactions = []) {
|
|
7053
|
+
function normalizeDocumentTableRowIdentities(state, rotateTextId, oldState, transactions = []) {
|
|
7048
7054
|
const rows = documentTableRows(state.doc);
|
|
7049
7055
|
const identifiedRows = rows.filter(({ node })=>hasDocumentTableRowIdentityComponent(node));
|
|
7050
7056
|
if (!identifiedRows.length) return null;
|
|
7051
7057
|
const retainedPositions = oldState ? retainedDocumentTableRowPositions(oldState, state, transactions) : new Set();
|
|
7052
|
-
const editedPositions = oldState && !transactions.some(isHistoryTransaction) ? editedDocumentTableRowPositions(oldState, state, transactions) : new Set();
|
|
7058
|
+
const editedPositions = oldState && rotateTextId() && !transactions.some(isHistoryTransaction) ? editedDocumentTableRowPositions(oldState, state, transactions) : new Set();
|
|
7053
7059
|
const ordered = [
|
|
7054
7060
|
...identifiedRows.filter((item)=>retainedPositions.has(item.position)),
|
|
7055
7061
|
...identifiedRows.filter((item)=>!retainedPositions.has(item.position))
|
|
@@ -8410,6 +8416,13 @@ const DocumentChange = Mark.create({
|
|
|
8410
8416
|
'data-change-id': attributes.id
|
|
8411
8417
|
})
|
|
8412
8418
|
},
|
|
8419
|
+
actorId: {
|
|
8420
|
+
default: '',
|
|
8421
|
+
parseHTML: (element)=>element.getAttribute('data-change-actor-id') ?? '',
|
|
8422
|
+
renderHTML: (attributes)=>attributes.actorId ? {
|
|
8423
|
+
'data-change-actor-id': attributes.actorId
|
|
8424
|
+
} : {}
|
|
8425
|
+
},
|
|
8413
8426
|
author: {
|
|
8414
8427
|
default: '',
|
|
8415
8428
|
parseHTML: (element)=>element.getAttribute('data-change-author') ?? '',
|
|
@@ -8451,10 +8464,12 @@ const DocumentChange = Mark.create({
|
|
|
8451
8464
|
acceptDocumentChange: (id)=>(props)=>resolveDocumentChangesCommand(props, this.type, 'accept', new Set([
|
|
8452
8465
|
id
|
|
8453
8466
|
])) > 0,
|
|
8467
|
+
acceptDocumentChanges: (ids)=>(props)=>resolveDocumentChangesCommand(props, this.type, 'accept', new Set(ids)) > 0,
|
|
8454
8468
|
rejectAllDocumentChanges: ()=>(props)=>resolveDocumentChangesCommand(props, this.type, 'reject') > 0,
|
|
8455
8469
|
rejectDocumentChange: (id)=>(props)=>resolveDocumentChangesCommand(props, this.type, 'reject', new Set([
|
|
8456
8470
|
id
|
|
8457
8471
|
])) > 0,
|
|
8472
|
+
rejectDocumentChanges: (ids)=>(props)=>resolveDocumentChangesCommand(props, this.type, 'reject', new Set(ids)) > 0,
|
|
8458
8473
|
replaceDocumentTextWithTrackedChange: (from, to, text)=>({ state, tr })=>{
|
|
8459
8474
|
if (from < 0 || to < from || to > state.doc.content.size) return false;
|
|
8460
8475
|
trackedReplacement(tr, state.doc, this.type, from, to, text, this.options.createChange);
|
|
@@ -8537,6 +8552,9 @@ function collectDocumentChanges(document1) {
|
|
|
8537
8552
|
changes.set(key, {
|
|
8538
8553
|
id,
|
|
8539
8554
|
kind,
|
|
8555
|
+
...work_document_changes_stringAttribute(mark.attrs.actorId) ? {
|
|
8556
|
+
actorId: work_document_changes_stringAttribute(mark.attrs.actorId)
|
|
8557
|
+
} : {},
|
|
8540
8558
|
author: work_document_changes_stringAttribute(mark.attrs.author) || '未知审阅者',
|
|
8541
8559
|
date: work_document_changes_stringAttribute(mark.attrs.date),
|
|
8542
8560
|
from: position,
|
|
@@ -8640,6 +8658,7 @@ function changeMark(type, kind, createChange) {
|
|
|
8640
8658
|
return type.create({
|
|
8641
8659
|
kind,
|
|
8642
8660
|
id: identity.id || createDocumentChangeId(),
|
|
8661
|
+
actorId: identity.actorId ?? '',
|
|
8643
8662
|
author: identity.author || 'A3S Work',
|
|
8644
8663
|
date: identity.date || new Date().toISOString()
|
|
8645
8664
|
});
|
|
@@ -15597,7 +15616,9 @@ function createWorkDocumentExtensions(options = {}) {
|
|
|
15597
15616
|
DocumentTableCell,
|
|
15598
15617
|
DocumentTableHeader,
|
|
15599
15618
|
DocumentTableRow,
|
|
15600
|
-
DocumentTableRowIdentity
|
|
15619
|
+
DocumentTableRowIdentity.configure({
|
|
15620
|
+
rotateTextId: options.rotateTrackedTextIdentities ?? (()=>true)
|
|
15621
|
+
}),
|
|
15601
15622
|
DocumentTableCommands,
|
|
15602
15623
|
DocumentTableFormatting,
|
|
15603
15624
|
DocumentTableSizing,
|
|
@@ -15614,7 +15635,9 @@ function createWorkDocumentExtensions(options = {}) {
|
|
|
15614
15635
|
'paragraph'
|
|
15615
15636
|
]
|
|
15616
15637
|
}),
|
|
15617
|
-
DocumentParagraphIdentity
|
|
15638
|
+
DocumentParagraphIdentity.configure({
|
|
15639
|
+
rotateTextId: options.rotateTrackedTextIdentities ?? (()=>true)
|
|
15640
|
+
}),
|
|
15618
15641
|
DocumentParagraphFormatting,
|
|
15619
15642
|
DocumentParagraphTabStops,
|
|
15620
15643
|
DocumentTab,
|
|
@@ -15864,6 +15887,142 @@ function deniedImmutableRecord(label) {
|
|
|
15864
15887
|
function deniedReviewMutation(session) {
|
|
15865
15888
|
throw new WorkOfficeCollaborationError('office.collaboration.permission_denied', `The '${session.mode}' collaboration mode cannot modify Document review records.`);
|
|
15866
15889
|
}
|
|
15890
|
+
function validatedWorkOfficeDocumentChangeDecisions(value) {
|
|
15891
|
+
if (!Array.isArray(value)) invalidInputSidecars('an array of tracked-change decisions');
|
|
15892
|
+
const ids = new Set();
|
|
15893
|
+
const changes = new Set();
|
|
15894
|
+
return value.map((candidate)=>{
|
|
15895
|
+
const decision = validatedDecision(candidate);
|
|
15896
|
+
if (ids.has(decision.id)) invalidInputSidecars(`a unique tracked-change decision ID; '${decision.id}' is repeated`);
|
|
15897
|
+
const change = changeIdentity(decision);
|
|
15898
|
+
if (changes.has(change)) invalidInputSidecars(`one final decision for tracked change '${decision.changeId}'`);
|
|
15899
|
+
ids.add(decision.id);
|
|
15900
|
+
changes.add(change);
|
|
15901
|
+
return decision;
|
|
15902
|
+
});
|
|
15903
|
+
}
|
|
15904
|
+
function initializeWorkOfficeDocumentChangeDecisions(records, order, decisions) {
|
|
15905
|
+
for (const decision of decisions){
|
|
15906
|
+
createDecisionRecord(records, decision);
|
|
15907
|
+
order.push([
|
|
15908
|
+
decision.id
|
|
15909
|
+
]);
|
|
15910
|
+
}
|
|
15911
|
+
}
|
|
15912
|
+
function readWorkOfficeDocumentChangeDecisions(records, order) {
|
|
15913
|
+
const decisions = validatedOrder(order, records, 'tracked-change decision').map((id)=>readDecisionRecord(requiredSharedMap(records, id, 'tracked-change decision'), id));
|
|
15914
|
+
const changes = new Set();
|
|
15915
|
+
for (const decision of decisions){
|
|
15916
|
+
const identity = changeIdentity(decision);
|
|
15917
|
+
if (changes.has(identity)) invalidSharedSidecars(`multiple final decisions for tracked change '${decision.changeId}'`);
|
|
15918
|
+
changes.add(identity);
|
|
15919
|
+
}
|
|
15920
|
+
return decisions;
|
|
15921
|
+
}
|
|
15922
|
+
function patchWorkOfficeDocumentChangeDecisions(records, order, previous, next) {
|
|
15923
|
+
const beforeById = new Map(previous.map((decision)=>[
|
|
15924
|
+
decision.id,
|
|
15925
|
+
decision
|
|
15926
|
+
]));
|
|
15927
|
+
for (const decision of previous){
|
|
15928
|
+
const candidate = next.find(({ id })=>id === decision.id);
|
|
15929
|
+
if (!candidate || !jsonEqual(candidate, decision)) immutableDecision(decision.id);
|
|
15930
|
+
}
|
|
15931
|
+
for (const decision of next)if (!beforeById.has(decision.id)) {
|
|
15932
|
+
if (!records.has(decision.id)) createDecisionRecord(records, decision);
|
|
15933
|
+
insertIntoOrder(order, next.map(({ id })=>id), decision.id);
|
|
15934
|
+
}
|
|
15935
|
+
}
|
|
15936
|
+
function assertWorkOfficeDocumentChangeDecisionConflicts(previous, next, shared) {
|
|
15937
|
+
assertNoAddedCollision(previous, next, shared, 'tracked-change decision');
|
|
15938
|
+
const nextById = new Map(next.map((decision)=>[
|
|
15939
|
+
decision.id,
|
|
15940
|
+
decision
|
|
15941
|
+
]));
|
|
15942
|
+
for (const decision of previous)if (!jsonEqual(nextById.get(decision.id), decision)) immutableDecision(decision.id);
|
|
15943
|
+
const sharedByChange = new Map(shared.map((decision)=>[
|
|
15944
|
+
changeIdentity(decision),
|
|
15945
|
+
decision
|
|
15946
|
+
]));
|
|
15947
|
+
const previousIds = new Set(previous.map(({ id })=>id));
|
|
15948
|
+
for (const decision of next){
|
|
15949
|
+
if (previousIds.has(decision.id)) continue;
|
|
15950
|
+
const current = sharedByChange.get(changeIdentity(decision));
|
|
15951
|
+
if (current && !jsonEqual(current, decision)) throw new WorkOfficeCollaborationError('office.collaboration.content_invalid', `Tracked change '${decision.changeId}' already has a different final decision.`);
|
|
15952
|
+
}
|
|
15953
|
+
}
|
|
15954
|
+
function validatedDecision(value) {
|
|
15955
|
+
if (!office_document_collaboration_sidecar_utils_isRecord(value)) invalidInputSidecars('valid tracked-change decision records');
|
|
15956
|
+
const decision = {
|
|
15957
|
+
id: requiredIdentifier(value.id, 'tracked-change decision'),
|
|
15958
|
+
changeId: requiredIdentifier(value.changeId, 'tracked change'),
|
|
15959
|
+
changeKind: office_document_collaboration_change_decisions_changeKind(value.changeKind, false),
|
|
15960
|
+
suggestedBy: requiredString(value.suggestedBy, 'suggestion author'),
|
|
15961
|
+
suggestedAt: requiredString(value.suggestedAt, 'suggestion date'),
|
|
15962
|
+
text: requiredString(value.text, 'suggestion text'),
|
|
15963
|
+
decision: decisionAction(value.decision, false),
|
|
15964
|
+
decidedBy: requiredString(value.decidedBy, 'decision author'),
|
|
15965
|
+
decidedAt: requiredString(value.decidedAt, 'decision date')
|
|
15966
|
+
};
|
|
15967
|
+
if (void 0 !== value.suggestedByActorId) decision.suggestedByActorId = requiredIdentifier(value.suggestedByActorId, 'suggestion actor');
|
|
15968
|
+
if (void 0 !== value.decidedByActorId) decision.decidedByActorId = requiredIdentifier(value.decidedByActorId, 'decision actor');
|
|
15969
|
+
return decision;
|
|
15970
|
+
}
|
|
15971
|
+
function createDecisionRecord(records, decision) {
|
|
15972
|
+
const record = new __rspack_external_yjs.Map();
|
|
15973
|
+
records.set(decision.id, record);
|
|
15974
|
+
for (const [key, value] of Object.entries(decision))record.set(key, value);
|
|
15975
|
+
}
|
|
15976
|
+
function readDecisionRecord(record, expectedId) {
|
|
15977
|
+
const id = requiredSharedIdentifier(record.get('id'), 'tracked-change decision');
|
|
15978
|
+
if (id !== expectedId) invalidSharedSidecars('tracked-change decision identity');
|
|
15979
|
+
const allowed = new Set([
|
|
15980
|
+
'id',
|
|
15981
|
+
'changeId',
|
|
15982
|
+
'changeKind',
|
|
15983
|
+
'suggestedByActorId',
|
|
15984
|
+
'suggestedBy',
|
|
15985
|
+
'suggestedAt',
|
|
15986
|
+
'text',
|
|
15987
|
+
'decision',
|
|
15988
|
+
'decidedByActorId',
|
|
15989
|
+
'decidedBy',
|
|
15990
|
+
'decidedAt'
|
|
15991
|
+
]);
|
|
15992
|
+
if (Array.from(record.keys()).some((key)=>!allowed.has(key))) invalidSharedSidecars('tracked-change decision fields');
|
|
15993
|
+
const decision = {
|
|
15994
|
+
id,
|
|
15995
|
+
changeId: requiredSharedIdentifier(record.get('changeId'), 'tracked change'),
|
|
15996
|
+
changeKind: office_document_collaboration_change_decisions_changeKind(record.get('changeKind'), true),
|
|
15997
|
+
suggestedBy: requiredSharedString(record.get('suggestedBy'), 'suggestion author'),
|
|
15998
|
+
suggestedAt: requiredSharedString(record.get('suggestedAt'), 'suggestion date'),
|
|
15999
|
+
text: requiredSharedString(record.get('text'), 'suggestion text'),
|
|
16000
|
+
decision: decisionAction(record.get('decision'), true),
|
|
16001
|
+
decidedBy: requiredSharedString(record.get('decidedBy'), 'decision author'),
|
|
16002
|
+
decidedAt: requiredSharedString(record.get('decidedAt'), 'decision date')
|
|
16003
|
+
};
|
|
16004
|
+
const suggestedByActorId = record.get('suggestedByActorId');
|
|
16005
|
+
if (void 0 !== suggestedByActorId) decision.suggestedByActorId = requiredSharedIdentifier(suggestedByActorId, 'suggestion actor');
|
|
16006
|
+
const decidedByActorId = record.get('decidedByActorId');
|
|
16007
|
+
if (void 0 !== decidedByActorId) decision.decidedByActorId = requiredSharedIdentifier(decidedByActorId, 'decision actor');
|
|
16008
|
+
return decision;
|
|
16009
|
+
}
|
|
16010
|
+
function changeIdentity(decision) {
|
|
16011
|
+
return `${decision.changeKind}:${decision.changeId}`;
|
|
16012
|
+
}
|
|
16013
|
+
function office_document_collaboration_change_decisions_changeKind(value, shared) {
|
|
16014
|
+
if ('insertion' === value || 'deletion' === value) return value;
|
|
16015
|
+
if (shared) invalidSharedSidecars('tracked-change decision kind');
|
|
16016
|
+
invalidInputSidecars('an insertion or deletion tracked-change kind');
|
|
16017
|
+
}
|
|
16018
|
+
function decisionAction(value, shared) {
|
|
16019
|
+
if ('accept' === value || 'reject' === value) return value;
|
|
16020
|
+
if (shared) invalidSharedSidecars('tracked-change decision action');
|
|
16021
|
+
invalidInputSidecars('an accept or reject tracked-change decision');
|
|
16022
|
+
}
|
|
16023
|
+
function immutableDecision(id) {
|
|
16024
|
+
throw new WorkOfficeCollaborationError('office.collaboration.permission_denied', `Tracked-change decision '${id}' is immutable and cannot be rewritten or removed.`);
|
|
16025
|
+
}
|
|
15867
16026
|
function validatedWorkOfficeDocumentBibliography(value) {
|
|
15868
16027
|
if (!office_document_collaboration_sidecar_utils_isRecord(value) || !isCitationStyle(value.style)) invalidInputSidecars('a supported bibliography style');
|
|
15869
16028
|
if (!Array.isArray(value.sources)) invalidInputSidecars('an array of bibliography sources');
|
|
@@ -16216,6 +16375,8 @@ function optionalSharedIdentifier(value, label) {
|
|
|
16216
16375
|
return void 0 === value ? void 0 : requiredSharedIdentifier(value, label);
|
|
16217
16376
|
}
|
|
16218
16377
|
function appendWorkOfficeDocumentRecordClaims(claims, previous, next) {
|
|
16378
|
+
const previousDecisions = new Set((previous.changeDecisions ?? []).map((decision)=>decision.id));
|
|
16379
|
+
for (const decision of next.changeDecisions ?? [])if (!previousDecisions.has(decision.id)) appendClaim(claims, 'change-decision', decision.id, decision);
|
|
16219
16380
|
const previousComments = new Map((previous.comments ?? []).map((comment)=>[
|
|
16220
16381
|
comment.id,
|
|
16221
16382
|
comment
|
|
@@ -16238,6 +16399,7 @@ function assertWorkOfficeDocumentRecordClaims(claims, sidecars) {
|
|
|
16238
16399
|
if (void 0 !== existing && existing !== claim.fingerprint) throw new WorkOfficeCollaborationError('office.collaboration.content_invalid', `The ${claimLabel(claim)} ID '${claim.id}' was concurrently assigned to different records.`);
|
|
16239
16400
|
fingerprints.set(identity, claim.fingerprint);
|
|
16240
16401
|
}
|
|
16402
|
+
for (const decision of sidecars.changeDecisions ?? [])assertClaimExists(fingerprints, 'change-decision', decision.id);
|
|
16241
16403
|
for (const comment of sidecars.comments ?? []){
|
|
16242
16404
|
assertClaimExists(fingerprints, 'comment', comment.id);
|
|
16243
16405
|
for (const reply of comment.replies ?? [])assertClaimExists(fingerprints, 'comment-reply', reply.id, comment.id);
|
|
@@ -16269,7 +16431,7 @@ function parsedClaim(rawClaim) {
|
|
|
16269
16431
|
const keys = Object.keys(value);
|
|
16270
16432
|
if (keys.some((key)=>'fingerprint' !== key && 'id' !== key && 'kind' !== key && 'parentId' !== key)) invalidSharedSidecars('record claim');
|
|
16271
16433
|
const kind = value.kind;
|
|
16272
|
-
if ('bibliography-source' !== kind && 'comment' !== kind && 'comment-reply' !== kind) invalidSharedSidecars('record claim kind');
|
|
16434
|
+
if ('bibliography-source' !== kind && 'change-decision' !== kind && 'comment' !== kind && 'comment-reply' !== kind) invalidSharedSidecars('record claim kind');
|
|
16273
16435
|
const id = requiredSharedIdentifier(value.id, 'record claim');
|
|
16274
16436
|
const fingerprint = requiredSharedString(value.fingerprint, 'record claim fingerprint');
|
|
16275
16437
|
const parentId = void 0 === value.parentId ? void 0 : requiredSharedIdentifier(value.parentId, 'record claim parent');
|
|
@@ -16302,6 +16464,7 @@ function claimIdentity(kind, id, parentId) {
|
|
|
16302
16464
|
]);
|
|
16303
16465
|
}
|
|
16304
16466
|
function claimLabel(claim) {
|
|
16467
|
+
if ('change-decision' === claim.kind) return 'tracked-change decision';
|
|
16305
16468
|
if ('comment' === claim.kind) return 'comment';
|
|
16306
16469
|
if ('bibliography-source' === claim.kind) return 'bibliography source';
|
|
16307
16470
|
return `reply in comment '${claim.parentId}'`;
|
|
@@ -16309,13 +16472,15 @@ function claimLabel(claim) {
|
|
|
16309
16472
|
const DOCUMENT_OPTIONS_ROOT = 'document.options';
|
|
16310
16473
|
const DOCUMENT_COMMENTS_ROOT = 'document.comments';
|
|
16311
16474
|
const DOCUMENT_COMMENT_ORDER_ROOT = 'document.comment-order';
|
|
16475
|
+
const DOCUMENT_CHANGE_DECISIONS_ROOT = 'document.change-decisions';
|
|
16476
|
+
const DOCUMENT_CHANGE_DECISION_ORDER_ROOT = 'document.change-decision-order';
|
|
16312
16477
|
const DOCUMENT_BIBLIOGRAPHY_ROOT = 'document.bibliography';
|
|
16313
16478
|
const DOCUMENT_BIBLIOGRAPHY_SOURCES_ROOT = 'document.bibliography.sources';
|
|
16314
16479
|
const DOCUMENT_BIBLIOGRAPHY_SOURCE_ORDER_ROOT = 'document.bibliography.source-order';
|
|
16315
16480
|
const DOCUMENT_RECORD_CLAIMS_ROOT = 'document.record-claims';
|
|
16316
16481
|
function assertWorkOfficeDocumentSidecarsEmpty(session) {
|
|
16317
16482
|
const roots = documentSidecarRoots(session);
|
|
16318
|
-
if (roots.options.size > 0 || roots.comments.size > 0 || roots.commentOrder.length > 0 || roots.bibliography.size > 0 || roots.bibliographySources.size > 0 || roots.bibliographySourceOrder.length > 0 || roots.recordClaims.length > 0) throw new WorkOfficeCollaborationError('office.collaboration.bootstrap_ambiguous', 'The Document collaboration sidecars contain data without initialized metadata.');
|
|
16483
|
+
if (roots.options.size > 0 || roots.comments.size > 0 || roots.commentOrder.length > 0 || roots.changeDecisions.size > 0 || roots.changeDecisionOrder.length > 0 || roots.bibliography.size > 0 || roots.bibliographySources.size > 0 || roots.bibliographySourceOrder.length > 0 || roots.recordClaims.length > 0) throw new WorkOfficeCollaborationError('office.collaboration.bootstrap_ambiguous', 'The Document collaboration sidecars contain data without initialized metadata.');
|
|
16319
16484
|
}
|
|
16320
16485
|
function initializeWorkOfficeDocumentSidecars(session, content) {
|
|
16321
16486
|
const roots = documentSidecarRoots(session);
|
|
@@ -16323,6 +16488,7 @@ function initializeWorkOfficeDocumentSidecars(session, content) {
|
|
|
16323
16488
|
appendWorkOfficeDocumentRecordClaims(roots.recordClaims, {}, sidecars);
|
|
16324
16489
|
if (void 0 !== sidecars.pageColor) roots.options.set('pageColor', sidecars.pageColor);
|
|
16325
16490
|
if (void 0 !== sidecars.trackChanges) roots.options.set('trackChanges', sidecars.trackChanges);
|
|
16491
|
+
if (void 0 !== sidecars.changeDecisions) initializeWorkOfficeDocumentChangeDecisions(roots.changeDecisions, roots.changeDecisionOrder, sidecars.changeDecisions);
|
|
16326
16492
|
if (void 0 !== sidecars.comments) {
|
|
16327
16493
|
roots.options.set('commentsPresent', true);
|
|
16328
16494
|
initializeWorkOfficeDocumentComments(roots.comments, roots.commentOrder, sidecars.comments);
|
|
@@ -16345,6 +16511,8 @@ function readWorkOfficeDocumentSidecars(session) {
|
|
|
16345
16511
|
if ('boolean' != typeof trackChanges) invalidSharedSidecars('track-changes setting');
|
|
16346
16512
|
result.trackChanges = trackChanges;
|
|
16347
16513
|
}
|
|
16514
|
+
if (roots.changeDecisionOrder.length > 0) result.changeDecisions = readWorkOfficeDocumentChangeDecisions(roots.changeDecisions, roots.changeDecisionOrder);
|
|
16515
|
+
else if (roots.changeDecisions.size > 0) invalidSharedSidecars('tracked-change decision order and record set');
|
|
16348
16516
|
const commentsPresent = optionalPresence(roots.options.get('commentsPresent'), 'comment');
|
|
16349
16517
|
if (true === commentsPresent || roots.commentOrder.length > 0) result.comments = readWorkOfficeDocumentComments(roots.comments, roots.commentOrder);
|
|
16350
16518
|
else if (roots.comments.size > 0) invalidSharedSidecars('comment order and record set');
|
|
@@ -16362,11 +16530,13 @@ function updateWorkOfficeDocumentSidecars(session, previous, next, origin) {
|
|
|
16362
16530
|
const roots = documentSidecarRoots(session);
|
|
16363
16531
|
const shared = readWorkOfficeDocumentSidecars(session);
|
|
16364
16532
|
assertWorkOfficeDocumentCommentConflicts(before.comments ?? [], after.comments ?? [], shared.comments ?? []);
|
|
16533
|
+
assertWorkOfficeDocumentChangeDecisionConflicts(before.changeDecisions ?? [], after.changeDecisions ?? [], shared.changeDecisions ?? []);
|
|
16365
16534
|
assertWorkOfficeDocumentBibliographyConflicts(before.bibliography, after.bibliography, shared.bibliography);
|
|
16366
16535
|
session.transact(()=>{
|
|
16367
16536
|
appendWorkOfficeDocumentRecordClaims(roots.recordClaims, before, after);
|
|
16368
16537
|
patchOptionalScalar(roots.options, 'pageColor', before.pageColor, after.pageColor);
|
|
16369
16538
|
patchOptionalScalar(roots.options, 'trackChanges', before.trackChanges, after.trackChanges);
|
|
16539
|
+
if (!jsonEqual(before.changeDecisions, after.changeDecisions)) patchWorkOfficeDocumentChangeDecisions(roots.changeDecisions, roots.changeDecisionOrder, before.changeDecisions ?? [], after.changeDecisions ?? []);
|
|
16370
16540
|
if (!jsonEqual(before.comments, after.comments)) {
|
|
16371
16541
|
patchPresence(roots.options, 'commentsPresent', before.comments, after.comments);
|
|
16372
16542
|
patchWorkOfficeDocumentComments(roots.comments, roots.commentOrder, before.comments ?? [], after.comments ?? []);
|
|
@@ -16390,9 +16560,19 @@ function workOfficeDocumentSidecarUndoScope(session) {
|
|
|
16390
16560
|
roots.recordClaims
|
|
16391
16561
|
];
|
|
16392
16562
|
}
|
|
16563
|
+
function workOfficeDocumentDecisionRootsChanged(session, transaction) {
|
|
16564
|
+
const roots = documentSidecarRoots(session);
|
|
16565
|
+
const changed = new Set(transaction.changedParentTypes.keys());
|
|
16566
|
+
return changed.has(roots.changeDecisions) || changed.has(roots.changeDecisionOrder);
|
|
16567
|
+
}
|
|
16393
16568
|
function workOfficeDocumentSidecarsChanged(session, transaction) {
|
|
16394
16569
|
const changed = new Set(transaction.changedParentTypes.keys());
|
|
16395
|
-
|
|
16570
|
+
const roots = documentSidecarRoots(session);
|
|
16571
|
+
return [
|
|
16572
|
+
...workOfficeDocumentSidecarUndoScope(session),
|
|
16573
|
+
roots.changeDecisions,
|
|
16574
|
+
roots.changeDecisionOrder
|
|
16575
|
+
].some((root)=>changed.has(root));
|
|
16396
16576
|
}
|
|
16397
16577
|
function validatedWorkOfficeDocumentSidecars(content) {
|
|
16398
16578
|
if (!content || 'document' !== content.type) invalidInputSidecars('a Document content value');
|
|
@@ -16405,6 +16585,7 @@ function validatedWorkOfficeDocumentSidecars(content) {
|
|
|
16405
16585
|
if ('boolean' != typeof content.trackChanges) invalidInputSidecars('a boolean track-changes setting');
|
|
16406
16586
|
result.trackChanges = content.trackChanges;
|
|
16407
16587
|
}
|
|
16588
|
+
if (void 0 !== content.changeDecisions) result.changeDecisions = validatedWorkOfficeDocumentChangeDecisions(content.changeDecisions);
|
|
16408
16589
|
if (void 0 !== content.comments) result.comments = validatedWorkOfficeDocumentComments(content.comments);
|
|
16409
16590
|
if (void 0 !== content.bibliography) result.bibliography = validatedWorkOfficeDocumentBibliography(content.bibliography);
|
|
16410
16591
|
return result;
|
|
@@ -16412,7 +16593,7 @@ function validatedWorkOfficeDocumentSidecars(content) {
|
|
|
16412
16593
|
function assertDocumentSidecarMutationAllowed(session, previous, next) {
|
|
16413
16594
|
if ('edit' === session.mode) return;
|
|
16414
16595
|
if ('comment' !== session.mode) return void assertWorkOfficeCollaborationEditable(session);
|
|
16415
|
-
if (!jsonEqual(previous.pageColor, next.pageColor) || !jsonEqual(previous.trackChanges, next.trackChanges) || !jsonEqual(previous.bibliography, next.bibliography)) throw new WorkOfficeCollaborationError('office.collaboration.permission_denied', 'The comment collaboration mode can modify only Document review records.');
|
|
16596
|
+
if (!jsonEqual(previous.pageColor, next.pageColor) || !jsonEqual(previous.trackChanges, next.trackChanges) || !jsonEqual(previous.changeDecisions, next.changeDecisions) || !jsonEqual(previous.bibliography, next.bibliography)) throw new WorkOfficeCollaborationError('office.collaboration.permission_denied', 'The comment collaboration mode can modify only Document review records.');
|
|
16416
16597
|
assertWorkOfficeDocumentCommentMutationAllowed(session, previous.comments ?? [], next.comments ?? []);
|
|
16417
16598
|
}
|
|
16418
16599
|
function documentSidecarRoots(session) {
|
|
@@ -16420,6 +16601,8 @@ function documentSidecarRoots(session) {
|
|
|
16420
16601
|
options: session.document.getMap(session.rootName(DOCUMENT_OPTIONS_ROOT)),
|
|
16421
16602
|
comments: session.document.getMap(session.rootName(DOCUMENT_COMMENTS_ROOT)),
|
|
16422
16603
|
commentOrder: session.document.getArray(session.rootName(DOCUMENT_COMMENT_ORDER_ROOT)),
|
|
16604
|
+
changeDecisions: session.document.getMap(session.rootName(DOCUMENT_CHANGE_DECISIONS_ROOT)),
|
|
16605
|
+
changeDecisionOrder: session.document.getArray(session.rootName(DOCUMENT_CHANGE_DECISION_ORDER_ROOT)),
|
|
16423
16606
|
bibliography: session.document.getMap(session.rootName(DOCUMENT_BIBLIOGRAPHY_ROOT)),
|
|
16424
16607
|
bibliographySources: session.document.getMap(session.rootName(DOCUMENT_BIBLIOGRAPHY_SOURCES_ROOT)),
|
|
16425
16608
|
bibliographySourceOrder: session.document.getArray(session.rootName(DOCUMENT_BIBLIOGRAPHY_SOURCE_ORDER_ROOT)),
|
|
@@ -16436,6 +16619,152 @@ function patchPresence(target, key, previous, next, absentValue) {
|
|
|
16436
16619
|
else if (void 0 !== previous) if (false === absentValue) target.set(key, false);
|
|
16437
16620
|
else target.delete(key);
|
|
16438
16621
|
}
|
|
16622
|
+
function workOfficeDocumentSuggestionTransactionAllowed(session, transaction) {
|
|
16623
|
+
const actor = session.actor;
|
|
16624
|
+
if (!actor || !transaction.docChanged || 0 === transaction.steps.length) return false;
|
|
16625
|
+
if (!transaction.steps.every((step)=>step instanceof ReplaceStep || (step instanceof AddMarkStep || step instanceof RemoveMarkStep) && 'documentChange' === step.mark.type.name)) return false;
|
|
16626
|
+
const before = strictDocumentChanges(transaction.before);
|
|
16627
|
+
const after = strictDocumentChanges(transaction.doc);
|
|
16628
|
+
if (!before || !after) return false;
|
|
16629
|
+
if (JSON.stringify(documentSuggestionBaseline(transaction.before)) !== JSON.stringify(documentSuggestionBaseline(transaction.doc))) return false;
|
|
16630
|
+
const beforeById = new Map(before.map((change)=>[
|
|
16631
|
+
change.id,
|
|
16632
|
+
change
|
|
16633
|
+
]));
|
|
16634
|
+
const afterById = new Map(after.map((change)=>[
|
|
16635
|
+
change.id,
|
|
16636
|
+
change
|
|
16637
|
+
]));
|
|
16638
|
+
for (const previous of before){
|
|
16639
|
+
const current = afterById.get(previous.id);
|
|
16640
|
+
if (!current) {
|
|
16641
|
+
if (previous.actorId !== actor.id) return false;
|
|
16642
|
+
continue;
|
|
16643
|
+
}
|
|
16644
|
+
if (!sameChangeIdentity(previous, current)) return false;
|
|
16645
|
+
if (previous.actorId !== actor.id && previous.text !== current.text) return false;
|
|
16646
|
+
if (previous.actorId === actor.id && 'deletion' === previous.kind && previous.text !== current.text) return false;
|
|
16647
|
+
}
|
|
16648
|
+
for (const current of after)if (!beforeById.has(current.id)) {
|
|
16649
|
+
if (current.actorId !== actor.id || current.author !== actor.name || !current.date || !current.text) return false;
|
|
16650
|
+
}
|
|
16651
|
+
return true;
|
|
16652
|
+
}
|
|
16653
|
+
function createWorkOfficeDocumentChangeDecisions(session, changes, decision, decidedAt = new Date().toISOString()) {
|
|
16654
|
+
const decidedBy = session.actor?.name ?? 'A3S Work 用户';
|
|
16655
|
+
return changes.map((change)=>({
|
|
16656
|
+
id: `${change.kind}:${change.id}`,
|
|
16657
|
+
changeId: change.id,
|
|
16658
|
+
changeKind: change.kind,
|
|
16659
|
+
...change.actorId ? {
|
|
16660
|
+
suggestedByActorId: change.actorId
|
|
16661
|
+
} : {},
|
|
16662
|
+
suggestedBy: change.author,
|
|
16663
|
+
suggestedAt: change.date,
|
|
16664
|
+
text: change.text,
|
|
16665
|
+
decision,
|
|
16666
|
+
...session.actor ? {
|
|
16667
|
+
decidedByActorId: session.actor.id
|
|
16668
|
+
} : {},
|
|
16669
|
+
decidedBy,
|
|
16670
|
+
decidedAt
|
|
16671
|
+
}));
|
|
16672
|
+
}
|
|
16673
|
+
function strictDocumentChanges(document1) {
|
|
16674
|
+
const changes = new Map();
|
|
16675
|
+
let valid = true;
|
|
16676
|
+
document1.descendants((node)=>{
|
|
16677
|
+
if (!valid || !node.isText || !node.text) return;
|
|
16678
|
+
const marks = node.marks.filter((mark)=>'documentChange' === mark.type.name);
|
|
16679
|
+
if (0 === marks.length) return;
|
|
16680
|
+
if (1 !== marks.length) {
|
|
16681
|
+
valid = false;
|
|
16682
|
+
return false;
|
|
16683
|
+
}
|
|
16684
|
+
const mark = marks[0];
|
|
16685
|
+
const id = strictString(mark.attrs.id);
|
|
16686
|
+
const kind = strictChangeKind(mark.attrs.kind);
|
|
16687
|
+
const author = strictString(mark.attrs.author);
|
|
16688
|
+
const date = strictString(mark.attrs.date);
|
|
16689
|
+
const actorId = optionalStrictString(mark.attrs.actorId);
|
|
16690
|
+
if (!id || !kind || null === author || null === date || null === actorId) {
|
|
16691
|
+
valid = false;
|
|
16692
|
+
return false;
|
|
16693
|
+
}
|
|
16694
|
+
const current = changes.get(id);
|
|
16695
|
+
const candidate = {
|
|
16696
|
+
id,
|
|
16697
|
+
kind,
|
|
16698
|
+
...actorId ? {
|
|
16699
|
+
actorId
|
|
16700
|
+
} : {},
|
|
16701
|
+
author,
|
|
16702
|
+
date,
|
|
16703
|
+
text: node.text
|
|
16704
|
+
};
|
|
16705
|
+
if (!current) return void changes.set(id, candidate);
|
|
16706
|
+
if (!sameChangeIdentity(current, candidate)) {
|
|
16707
|
+
valid = false;
|
|
16708
|
+
return false;
|
|
16709
|
+
}
|
|
16710
|
+
current.text += node.text;
|
|
16711
|
+
});
|
|
16712
|
+
return valid ? Array.from(changes.values()) : null;
|
|
16713
|
+
}
|
|
16714
|
+
function documentSuggestionBaseline(node) {
|
|
16715
|
+
const json = node.toJSON();
|
|
16716
|
+
if (node.isText) {
|
|
16717
|
+
const change = node.marks.find((mark)=>'documentChange' === mark.type.name);
|
|
16718
|
+
if (change?.attrs.kind === 'insertion') return null;
|
|
16719
|
+
const marks = node.marks.filter((mark)=>'documentChange' !== mark.type.name).map((mark)=>mark.toJSON());
|
|
16720
|
+
if (marks.length > 0) return {
|
|
16721
|
+
...json,
|
|
16722
|
+
marks
|
|
16723
|
+
};
|
|
16724
|
+
const { marks: _marks, ...withoutMarks } = json;
|
|
16725
|
+
return withoutMarks;
|
|
16726
|
+
}
|
|
16727
|
+
const content = [];
|
|
16728
|
+
node.forEach((child)=>{
|
|
16729
|
+
const projected = documentSuggestionBaseline(child);
|
|
16730
|
+
if (null !== projected) appendSuggestionBaselineNode(content, projected);
|
|
16731
|
+
});
|
|
16732
|
+
if (content.length > 0) return {
|
|
16733
|
+
...json,
|
|
16734
|
+
content
|
|
16735
|
+
};
|
|
16736
|
+
const { content: _content, ...withoutContent } = json;
|
|
16737
|
+
return withoutContent;
|
|
16738
|
+
}
|
|
16739
|
+
function appendSuggestionBaselineNode(content, projected) {
|
|
16740
|
+
const previous = content.at(-1);
|
|
16741
|
+
if (isSuggestionBaselineText(previous) && isSuggestionBaselineText(projected) && JSON.stringify(previous.marks ?? []) === JSON.stringify(projected.marks ?? [])) {
|
|
16742
|
+
content[content.length - 1] = {
|
|
16743
|
+
...previous,
|
|
16744
|
+
text: previous.text + projected.text
|
|
16745
|
+
};
|
|
16746
|
+
return;
|
|
16747
|
+
}
|
|
16748
|
+
content.push(projected);
|
|
16749
|
+
}
|
|
16750
|
+
function isSuggestionBaselineText(value) {
|
|
16751
|
+
if (!value || 'object' != typeof value) return false;
|
|
16752
|
+
const candidate = value;
|
|
16753
|
+
return 'text' === candidate.type && 'string' == typeof candidate.text;
|
|
16754
|
+
}
|
|
16755
|
+
function sameChangeIdentity(left, right) {
|
|
16756
|
+
return left.id === right.id && left.kind === right.kind && left.actorId === right.actorId && left.author === right.author && left.date === right.date;
|
|
16757
|
+
}
|
|
16758
|
+
function strictString(value) {
|
|
16759
|
+
return 'string' == typeof value && value.trim() === value && value ? value : null;
|
|
16760
|
+
}
|
|
16761
|
+
function optionalStrictString(value) {
|
|
16762
|
+
if (void 0 === value || '' === value) return;
|
|
16763
|
+
return strictString(value);
|
|
16764
|
+
}
|
|
16765
|
+
function strictChangeKind(value) {
|
|
16766
|
+
return 'insertion' === value || 'deletion' === value ? value : null;
|
|
16767
|
+
}
|
|
16439
16768
|
const DOCUMENT_CONTENT_ROOT = 'document.content';
|
|
16440
16769
|
const MAX_DOCUMENT_COMMENT_HISTORY = 100;
|
|
16441
16770
|
const mountedDocumentBindings = new WeakMap();
|
|
@@ -16518,7 +16847,8 @@ class WorkOfficeDocumentCollaborationBindingImpl {
|
|
|
16518
16847
|
assertWorkOfficeCollaborationOrigin(this.origin);
|
|
16519
16848
|
const builtIns = createWorkDocumentExtensions({
|
|
16520
16849
|
...options.workExtensions,
|
|
16521
|
-
collaborative: true
|
|
16850
|
+
collaborative: true,
|
|
16851
|
+
rotateTrackedTextIdentities: ()=>'suggest' !== session.mode
|
|
16522
16852
|
});
|
|
16523
16853
|
const additional = options.additionalExtensions ?? [];
|
|
16524
16854
|
assertBehaviorOnlyExtensions(additional);
|
|
@@ -16541,7 +16871,7 @@ class WorkOfficeDocumentCollaborationBindingImpl {
|
|
|
16541
16871
|
]));
|
|
16542
16872
|
const existing = mountedDocumentBindings.get(session.document);
|
|
16543
16873
|
if (existing) throw new WorkOfficeCollaborationError('office.collaboration.content_invalid', 'Only one Document collaboration binding may use a local Y.Doc at a time. Give each editor client its own synchronized Y.Doc.');
|
|
16544
|
-
const undoScope = 'comment' === session.mode ? [
|
|
16874
|
+
const undoScope = 'comment' === session.mode || 'suggest' === session.mode ? [
|
|
16545
16875
|
this.fragment
|
|
16546
16876
|
] : [
|
|
16547
16877
|
this.fragment,
|
|
@@ -16559,7 +16889,7 @@ class WorkOfficeDocumentCollaborationBindingImpl {
|
|
|
16559
16889
|
const restore = restorable.restore?.bind(this.#undoManager);
|
|
16560
16890
|
if (restore) restorable.restore = ()=>{
|
|
16561
16891
|
restore();
|
|
16562
|
-
this.#undoManager.addToScope('comment' === this.#session.mode ? this.fragment : [
|
|
16892
|
+
this.#undoManager.addToScope('comment' === this.#session.mode || 'suggest' === this.#session.mode ? this.fragment : [
|
|
16563
16893
|
this.fragment,
|
|
16564
16894
|
...workOfficeDocumentSidecarUndoScope(this.#session)
|
|
16565
16895
|
]);
|
|
@@ -16602,6 +16932,36 @@ class WorkOfficeDocumentCollaborationBindingImpl {
|
|
|
16602
16932
|
}
|
|
16603
16933
|
return changed;
|
|
16604
16934
|
}
|
|
16935
|
+
decideChanges(editor, changeIds, decision, options = {}) {
|
|
16936
|
+
this.ensureActive();
|
|
16937
|
+
assertWorkOfficeCollaborationEditable(this.#session);
|
|
16938
|
+
if (editor.isDestroyed || 0 === changeIds.length) return false;
|
|
16939
|
+
const requested = new Set(changeIds);
|
|
16940
|
+
const changes = collectDocumentChanges(editor.state.doc).filter((change)=>requested.has(change.id));
|
|
16941
|
+
if (changes.length !== requested.size) return false;
|
|
16942
|
+
const before = this.content();
|
|
16943
|
+
const decisions = createWorkOfficeDocumentChangeDecisions(this.#session, changes, decision, options.decidedAt);
|
|
16944
|
+
const existing = new Set((before.changeDecisions ?? []).map(({ id })=>id));
|
|
16945
|
+
if (decisions.some(({ id })=>existing.has(id))) throw new WorkOfficeCollaborationError('office.collaboration.permission_denied', 'A tracked change with a final decision cannot be decided again.');
|
|
16946
|
+
const origin = this.#session.createOrigin(this.#session.localOrigin.kind);
|
|
16947
|
+
let handled = false;
|
|
16948
|
+
this.#session.transact(()=>{
|
|
16949
|
+
handled = 'accept' === decision ? editor.commands.acceptDocumentChanges(changeIds) : editor.commands.rejectDocumentChanges(changeIds);
|
|
16950
|
+
if (!handled) return;
|
|
16951
|
+
updateWorkOfficeDocumentSidecars(this.#session, before, {
|
|
16952
|
+
...before,
|
|
16953
|
+
changeDecisions: [
|
|
16954
|
+
...before.changeDecisions ?? [],
|
|
16955
|
+
...decisions
|
|
16956
|
+
]
|
|
16957
|
+
}, origin);
|
|
16958
|
+
}, origin);
|
|
16959
|
+
if (handled) {
|
|
16960
|
+
this.#undoManager.clear();
|
|
16961
|
+
this.#onHistoryChange();
|
|
16962
|
+
}
|
|
16963
|
+
return handled;
|
|
16964
|
+
}
|
|
16605
16965
|
canUndo() {
|
|
16606
16966
|
this.ensureActive();
|
|
16607
16967
|
if ('comment' === this.#session.mode) return this.#commentUndoStack.length > 0 || this.#undoManager.canUndo();
|
|
@@ -16618,6 +16978,10 @@ class WorkOfficeDocumentCollaborationBindingImpl {
|
|
|
16618
16978
|
assertWorkOfficeCollaborationWritable(this.#session, 'document-comment');
|
|
16619
16979
|
return this.applyCommentHistory('undo');
|
|
16620
16980
|
}
|
|
16981
|
+
if ('suggest' === this.#session.mode) {
|
|
16982
|
+
assertWorkOfficeCollaborationWritable(this.#session, 'document-suggestion');
|
|
16983
|
+
return null !== this.#undoManager.undo();
|
|
16984
|
+
}
|
|
16621
16985
|
assertWorkOfficeCollaborationEditable(this.#session);
|
|
16622
16986
|
return null !== this.#undoManager.undo();
|
|
16623
16987
|
}
|
|
@@ -16627,6 +16991,10 @@ class WorkOfficeDocumentCollaborationBindingImpl {
|
|
|
16627
16991
|
assertWorkOfficeCollaborationWritable(this.#session, 'document-comment');
|
|
16628
16992
|
return this.applyCommentHistory('redo');
|
|
16629
16993
|
}
|
|
16994
|
+
if ('suggest' === this.#session.mode) {
|
|
16995
|
+
assertWorkOfficeCollaborationWritable(this.#session, 'document-suggestion');
|
|
16996
|
+
return null !== this.#undoManager.redo();
|
|
16997
|
+
}
|
|
16630
16998
|
assertWorkOfficeCollaborationEditable(this.#session);
|
|
16631
16999
|
return null !== this.#undoManager.redo();
|
|
16632
17000
|
}
|
|
@@ -16669,6 +17037,10 @@ class WorkOfficeDocumentCollaborationBindingImpl {
|
|
|
16669
17037
|
if (transaction.origin === ySyncPluginKey) transaction.origin = this.origin;
|
|
16670
17038
|
};
|
|
16671
17039
|
#onTransaction = (transaction)=>{
|
|
17040
|
+
if ('suggest' === this.#session.mode && workOfficeDocumentDecisionRootsChanged(this.#session, transaction)) {
|
|
17041
|
+
this.#undoManager.clear();
|
|
17042
|
+
this.#onHistoryChange();
|
|
17043
|
+
}
|
|
16672
17044
|
if (this.#destroyed || this.#destroyRequested || !transactionTouchesRoot(transaction, this.fragment) && !workOfficeDocumentSidecarsChanged(this.#session, transaction)) return;
|
|
16673
17045
|
const local = transaction.origin === ySyncPluginKey || transaction.origin === this.origin || transaction.origin === this.#undoManager;
|
|
16674
17046
|
this.#pendingLocal = this.#pendingChange ? this.#pendingLocal && local : local;
|
|
@@ -16944,7 +17316,7 @@ function documentCollaborationPermissionExtension(session) {
|
|
|
16944
17316
|
return [
|
|
16945
17317
|
new Plugin({
|
|
16946
17318
|
filterTransaction (transaction) {
|
|
16947
|
-
return 'edit' === session.mode || !transaction.docChanged || isChangeOrigin(transaction) || 'comment' === session.mode && transaction.steps.length > 0 && transaction.steps.every((step)=>(step instanceof AddMarkStep || step instanceof RemoveMarkStep) && 'documentComment' === step.mark.type.name);
|
|
17319
|
+
return 'edit' === session.mode || !transaction.docChanged || isChangeOrigin(transaction) || 'comment' === session.mode && transaction.steps.length > 0 && transaction.steps.every((step)=>(step instanceof AddMarkStep || step instanceof RemoveMarkStep) && 'documentComment' === step.mark.type.name) || 'suggest' === session.mode && workOfficeDocumentSuggestionTransactionAllowed(session, transaction);
|
|
16948
17320
|
}
|
|
16949
17321
|
})
|
|
16950
17322
|
];
|