Revised widget API for batch body modifications

This commit is contained in:
Rainer Simon 2021-07-03 08:10:02 +02:00
parent 9cb80ca6a4
commit e84bebc9b9
1 changed files with 88 additions and 44 deletions

View File

@ -91,43 +91,29 @@ export default class Editor extends Component {
return meta; return meta;
} }
/** Shorthand **/ /** Shorthand **/
updateCurrentAnnotation = (diff, saveImmediately) => { updateCurrentAnnotation = (diff, saveImmediately) => this.setState({
this.setState({ currentAnnotation: this.state.currentAnnotation.clone(diff)
currentAnnotation: this.state.currentAnnotation.clone(diff) }, () => {
}, () => { if (saveImmediately)
if (saveImmediately) this.onOk();
this.onOk(); })
})
}
/** onAppendBody = (body, saveImmediately) => this.updateCurrentAnnotation({
* Appends a body to the current annotation. For convenience: also body: [
* takes an array of bodies as argument. ...this.state.currentAnnotation.bodies,
* @param bodyOrBodies the body or list of bodies to append { ...body, ...this.creationMeta(body) }
* @param saveImmediately set to true to save & close immediately ]
*/ }, saveImmediately);
onAppendBody = (bodyOrBodies, saveImmediately) => {
const toAppend = toArray(bodyOrBodies).map(b =>
({ ...b, ...this.creationMeta(b) }));
this.updateCurrentAnnotation({ onUpdateBody = (previous, updated, saveImmediately) => this.updateCurrentAnnotation({
body: [ ...this.state.currentAnnotation.bodies, ...toAppend ] body: this.state.currentAnnotation.bodies.map(body =>
}, saveImmediately); body === previous ? { ...updated, ...this.creationMeta(updated) } : body)
} }, saveImmediately);
/** onRemoveBody = (body, saveImmediately) => this.updateCurrentAnnotation({
* Updates a previous body with the given body. body: this.state.currentAnnotation.bodies.filter(b => b !== body)
* @param previous the body to replace }, saveImmediately);
* @param updated the body to replace with
* @param saveImmediately set to true to save & close immediately
*/
onUpdateBody = (previous, updated, saveImmediately) => {
this.updateCurrentAnnotation({
body: this.state.currentAnnotation.bodies.map(body =>
body === previous ? { ...updated, ...this.creationMeta(updated) } : body)
}, saveImmediately);
}
/** /**
* For convenience: an 'append or update' shorthand. * For convenience: an 'append or update' shorthand.
@ -150,18 +136,76 @@ export default class Editor extends Component {
} }
} }
/** /**
* Removes the given body from the current annotation. For * Advanced method for applying a batch of body changes
* convenience: also takes an array of bodies as argument. * in one go (append, remove update), optionally saving
* @param bodyOrBodies the body or list of bodies to remove * immediately afterwards. The argument is an array of
* @param saveImmediately set to true to save & close immediately * diff objects with the following structure:
*
* [
* { action: 'append', body: bodyToAppend },
* { action: 'update', previous: prevBody, updated: updatedBody }
* { action: 'remove', body: bodyToRemove },
*
* // Normal upsert, previous is optional
* { action: 'upsert', previous: prevBody, updated: updatedBody }
*
* // Auto-upsert based on purpose
* { action: 'upsert', body: bodyToUpser }
* ]
*/ */
onRemoveBody = (bodyOrBodies, saveImmediately) => { onBatchModify = (diffs, saveImmediately) => {
const toRemove = toArray(bodyOrBodies); // First, find previous bodies for auto upserts
const autoUpserts = diffs
.filter(d => d.action === 'upsert' && d.body)
.map(d => ({
previous: this.state.currentAnnotation.bodies.find(b => b.purpose === d.body.purpose),
updated: { ...d.body, ...this.creationMeta(d.body)}
}));
this.updateCurrentAnnotation({ const toRemove = diffs
body: this.state.currentAnnotation.bodies.filter(b => !toRemove.includes(b)) .filter(d => d.action === 'remove')
}, saveImmediately); .map(d => d.body);
const toAppend = [
...diffs
.filter(d => (d.action === 'append') || (d.action === 'upsert' && d.updated && !d.previous))
.map(d => ({ ...d.body, ...this.creationMeta(d.body) })),
...autoUpserts
.filter(d => !d.previous)
.map(d => d.updated)
];
const toUpdate = [
...diffs
.filter(d => (d.action === 'update') || (d.action === 'upsert' && d.updated && d.previous))
.map(d => ({
previous: d.previous,
updated: { ...d.updated, ...this.creationMeta(d.updated) }
})),
...autoUpserts
.filter(d => d.previous)
];
const updatedBodies = [
// Current bodies
...this.state.currentAnnotation.bodies
// Remvoe
.filter(b => !toRemove.includes(b))
// Update
.map(b => {
const { updated } = toUpdate.find(t => t.previous === b);
return updated ? updated : body;
}),
// Append
...toAppend
]
this.updateCurrentAnnotation({ body: updatedBodies }, saveImmediately);
} }
/** /**