- move SlateEditor and dependencies to its own folder
- remove Immutable
- remove redux-persist-immutable
- remobe redux-immutable
- update libraries
- added tests on store manipulations (accessor and reducers)
import { put } from 'redux-saga/effects';
import * as R from 'ramda';
import { ActionEnum } from '../constants';
const testLocalListHas = R.useWith(R.compose,[R.contains, R.prop]);
const getPropValues = R.compose(R.values, R.prop);
export const SyncMixin = Base => class extends Base {
constructor(syncEntries, client) {
super();
this.syncEntries = syncEntries;
this.client = client;
this.localDiffs = null;
}
* loadFromRemote() {
const objIds = R.compose(R.map(R.prop('ext_id')),R.reject(R.propEq('action', ActionEnum.UPDATED)))(this.syncEntries);
if(objIds.length === 0) {
return ;
}
//TODO: manage pagination
const remoteObjs = yield this.client.get(this.getRemoteLoadUrl(), { ext_id__in: objIds.join(',') })
for (var remoteObj of remoteObjs.results) {
if(testLocalListHas(remoteObj.ext_id, 'deleted')(this.localDiffs)) {
// if(this.localDiffs.get('deleted').has(remoteObj.ext_id)) {
// The session has been deleted locally, we will delete it later
continue;
}
if(testLocalListHas(remoteObj.ext_id, 'created')(this.localDiffs)) {
// if(this.localDiffs.get('created').has(remoteObj.ext_id)) {
// The session has been modified both locally and remotely
// the server wins, it will be loaded locally, we must remove it from the list of locally changed sessions
this.localDiffs = R.merge(this.localDiffs, { created: R.omit([remoteObj.ext_id,], this.localDiffs.created) } );
// const newCreatedMap = this.localDiffs.get('created').delete(remoteObj.ext_id);
// this.localDiffs = this.localDiffs.set('created', newCreatedMap);
}
if(testLocalListHas(remoteObj.ext_id, 'updated')(this.localDiffs)) {
// The session has been modified both locally and remotely
// the server wins, it will be loaded locally, we must remove it from the list of locally changed sessions
// const newModifiedMap = this.localDiffs.get('updated').delete(remoteObj.ext_id);
// this.localDiffs = this.localDiffs.set('updated', newModifiedMap);
this.localDiffs = R.merge(this.localDiffs, { updated: R.omit([remoteObj.ext_id,], this.localDiffs.updated) } );
}
let objRecord = this.getLocalRecord(remoteObj);
yield put(this.loadObj(objRecord));
}
}
* deleteFromRemote() {
const objToDelete = this.syncEntries
.filter((syncObj) => syncObj.action === 2)
.map((syncObj) => syncObj.ext_id);
let deleteObjs = R.prop('deleted', this.localDiffs);
let updatedObjs = R.prop('updated', this.localDiffs);
let createdObjs = R.prop('created', this.localDiffs);
for (var objId of objToDelete) {
const omitObjId = R.omit([objId,])
deleteObjs = omitObjId(deleteObjs);
updatedObjs = omitObjId(updatedObjs);
createdObjs = omitObjId(createdObjs);
yield put(this.doDeleteLocalObj(objId));
}
this.localDiffs = {created: createdObjs, updated: updatedObjs, deleted: deleteObjs};
}
* syncObjects() {
this.localDiffs = yield this.getLocalDiffs();
yield this.loadFromRemote();
yield this.deleteFromRemote();
let localObjInst;
const getLocalDiffPropValues = R.flip(getPropValues)(this.localDiffs);
// delete remote obj
for(localObjInst of getLocalDiffPropValues('deleted')) {
try {
yield this.client.delete(this.getRemoteDeleteUrl(localObjInst));
} catch(err) {
if(err.status !== 404) {
//TODO: better error handling ???
console.log("error whe deleting object", err);
}
// otherwise, this is ok
}
yield put(this.doDeleteLocalObj(localObjInst._id));
}
for(localObjInst of getLocalDiffPropValues('created')) {
const remoteData = this.getRemoteData(localObjInst);
//TODO: SET VERSION !!!!
yield this.client.post(this.getRemoteCreateUrl(localObjInst), remoteData);
yield put(this.resetLocalObj(localObjInst));
}
for(localObjInst of getLocalDiffPropValues('updated')) {
const remoteData = this.getRemoteData(localObjInst);
//TODO: SET VERSION !!!!
yield this.client.put(this.getRemoteUpdateUrl(localObjInst), remoteData);
yield put(this.resetLocalObj(localObjInst));
}
}
}
export default SyncMixin;