|
|
|
|
@ -18,25 +18,35 @@
|
|
|
|
|
this.id = session.id;
|
|
|
|
|
this.version = version;
|
|
|
|
|
this.collection = collection;
|
|
|
|
|
this.initialObjects = [];
|
|
|
|
|
this.initialObjects = {};
|
|
|
|
|
this.hash = this._getHash();
|
|
|
|
|
|
|
|
|
|
// We need use data from export instead of initialData
|
|
|
|
|
// Otherwise we have differ keys order and JSON comparison code incorrect
|
|
|
|
|
const exported = this.collection.export();
|
|
|
|
|
|
|
|
|
|
this._resetState();
|
|
|
|
|
for (const shape of exported.shapes) {
|
|
|
|
|
this.initialObjects[shape.id] = shape;
|
|
|
|
|
this.initialObjects.shapes[shape.id] = shape;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const track of exported.tracks) {
|
|
|
|
|
this.initialObjects[track.id] = track;
|
|
|
|
|
this.initialObjects.tracks[track.id] = track;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const tag of exported.tags) {
|
|
|
|
|
this.initialObjects[tag.id] = tag;
|
|
|
|
|
this.initialObjects.tags[tag.id] = tag;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_resetState() {
|
|
|
|
|
this.initialObjects = {
|
|
|
|
|
shapes: {},
|
|
|
|
|
tracks: {},
|
|
|
|
|
tags: {},
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_getHash() {
|
|
|
|
|
const exported = this.collection.export();
|
|
|
|
|
return JSON.stringify(exported);
|
|
|
|
|
@ -95,9 +105,9 @@
|
|
|
|
|
// Find created and updated objects
|
|
|
|
|
for (const type of Object.keys(exported)) {
|
|
|
|
|
for (const object of exported[type]) {
|
|
|
|
|
if (object.id in this.initialObjects) {
|
|
|
|
|
if (object.id in this.initialObjects[type]) {
|
|
|
|
|
const exportedHash = JSON.stringify(object);
|
|
|
|
|
const initialHash = JSON.stringify(this.initialObjects[object.id]);
|
|
|
|
|
const initialHash = JSON.stringify(this.initialObjects[type][object.id]);
|
|
|
|
|
if (exportedHash !== initialHash) {
|
|
|
|
|
splitted.updated[type].push(object);
|
|
|
|
|
}
|
|
|
|
|
@ -113,24 +123,22 @@
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Now find deleted objects
|
|
|
|
|
const indexes = exported.tracks.concat(exported.shapes)
|
|
|
|
|
.concat(exported.tags).map(object => object.id);
|
|
|
|
|
|
|
|
|
|
for (const id of Object.keys(this.initialObjects)) {
|
|
|
|
|
if (!indexes.includes(+id)) {
|
|
|
|
|
const object = this.initialObjects[id];
|
|
|
|
|
let type = null;
|
|
|
|
|
if ('shapes' in object) {
|
|
|
|
|
type = 'tracks';
|
|
|
|
|
} else if ('points' in object) {
|
|
|
|
|
type = 'shapes';
|
|
|
|
|
} else {
|
|
|
|
|
type = 'tags';
|
|
|
|
|
const indexes = {
|
|
|
|
|
shapes: exported.shapes.map((object) => +object.id),
|
|
|
|
|
tracks: exported.tracks.map((object) => +object.id),
|
|
|
|
|
tags: exported.tags.map((object) => +object.id),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
for (const type of Object.keys(this.initialObjects)) {
|
|
|
|
|
for (const id of Object.keys(this.initialObjects[type])) {
|
|
|
|
|
if (!indexes[type].includes(+id)) {
|
|
|
|
|
const object = this.initialObjects[type][id];
|
|
|
|
|
splitted.deleted[type].push(object);
|
|
|
|
|
}
|
|
|
|
|
splitted.deleted[type].push(object);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return splitted;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -164,9 +172,9 @@
|
|
|
|
|
_receiveIndexes(exported) {
|
|
|
|
|
// Receive client indexes before saving
|
|
|
|
|
const indexes = {
|
|
|
|
|
tracks: exported.tracks.map(track => track.clientID),
|
|
|
|
|
shapes: exported.shapes.map(shape => shape.clientID),
|
|
|
|
|
tags: exported.tags.map(tag => tag.clientID),
|
|
|
|
|
tracks: exported.tracks.map((track) => track.clientID),
|
|
|
|
|
shapes: exported.shapes.map((shape) => shape.clientID),
|
|
|
|
|
tags: exported.tags.map((tag) => tag.clientID),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Remove them from the request body
|
|
|
|
|
@ -192,9 +200,7 @@
|
|
|
|
|
if (flush) {
|
|
|
|
|
onUpdate('New objects are being saved..');
|
|
|
|
|
const indexes = this._receiveIndexes(exported);
|
|
|
|
|
const savedData = await this._put(Object.assign({}, exported, {
|
|
|
|
|
version: this.version,
|
|
|
|
|
}));
|
|
|
|
|
const savedData = await this._put({ ...exported, version: this.version });
|
|
|
|
|
this.version = savedData.version;
|
|
|
|
|
this.collection.flush = false;
|
|
|
|
|
|
|
|
|
|
@ -202,9 +208,12 @@
|
|
|
|
|
this._updateCreatedObjects(savedData, indexes);
|
|
|
|
|
|
|
|
|
|
onUpdate('Initial state is being updated');
|
|
|
|
|
for (const object of savedData.shapes
|
|
|
|
|
.concat(savedData.tracks).concat(savedData.tags)) {
|
|
|
|
|
this.initialObjects[object.id] = object;
|
|
|
|
|
|
|
|
|
|
this._resetState();
|
|
|
|
|
for (const type of Object.keys(this.initialObjects)) {
|
|
|
|
|
for (const object of savedData[type]) {
|
|
|
|
|
this.initialObjects[type][object.id] = object;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
const {
|
|
|
|
|
@ -215,44 +224,41 @@
|
|
|
|
|
|
|
|
|
|
onUpdate('New objects are being saved..');
|
|
|
|
|
const indexes = this._receiveIndexes(created);
|
|
|
|
|
const createdData = await this._create(Object.assign({}, created, {
|
|
|
|
|
version: this.version,
|
|
|
|
|
}));
|
|
|
|
|
const createdData = await this._create({ ...created, version: this.version });
|
|
|
|
|
this.version = createdData.version;
|
|
|
|
|
|
|
|
|
|
onUpdate('Saved objects are being updated in the client');
|
|
|
|
|
this._updateCreatedObjects(createdData, indexes);
|
|
|
|
|
|
|
|
|
|
onUpdate('Initial state is being updated');
|
|
|
|
|
for (const object of createdData.shapes
|
|
|
|
|
.concat(createdData.tracks).concat(createdData.tags)) {
|
|
|
|
|
this.initialObjects[object.id] = object;
|
|
|
|
|
for (const type of Object.keys(this.initialObjects)) {
|
|
|
|
|
for (const object of createdData[type]) {
|
|
|
|
|
this.initialObjects[type][object.id] = object;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onUpdate('Changed objects are being saved..');
|
|
|
|
|
this._receiveIndexes(updated);
|
|
|
|
|
const updatedData = await this._update(Object.assign({}, updated, {
|
|
|
|
|
version: this.version,
|
|
|
|
|
}));
|
|
|
|
|
this.version = createdData.version;
|
|
|
|
|
const updatedData = await this._update({ ...updated, version: this.version });
|
|
|
|
|
this.version = updatedData.version;
|
|
|
|
|
|
|
|
|
|
onUpdate('Initial state is being updated');
|
|
|
|
|
for (const object of updatedData.shapes
|
|
|
|
|
.concat(updatedData.tracks).concat(updatedData.tags)) {
|
|
|
|
|
this.initialObjects[object.id] = object;
|
|
|
|
|
for (const type of Object.keys(this.initialObjects)) {
|
|
|
|
|
for (const object of updatedData[type]) {
|
|
|
|
|
this.initialObjects[type][object.id] = object;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onUpdate('Changed objects are being saved..');
|
|
|
|
|
this._receiveIndexes(deleted);
|
|
|
|
|
const deletedData = await this._delete(Object.assign({}, deleted, {
|
|
|
|
|
version: this.version,
|
|
|
|
|
}));
|
|
|
|
|
const deletedData = await this._delete({ ...deleted, version: this.version });
|
|
|
|
|
this._version = deletedData.version;
|
|
|
|
|
|
|
|
|
|
onUpdate('Initial state is being updated');
|
|
|
|
|
for (const object of deletedData.shapes
|
|
|
|
|
.concat(deletedData.tracks).concat(deletedData.tags)) {
|
|
|
|
|
delete this.initialObjects[object.id];
|
|
|
|
|
for (const type of Object.keys(this.initialObjects)) {
|
|
|
|
|
for (const object of deletedData[type]) {
|
|
|
|
|
delete this.initialObjects[type][object.id];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|