client/src/sagas/BaseSyncronizer.js
author Riwad Salim
Wed, 15 Aug 2018 23:39:02 +0200
changeset 145 5d2bc8c877ea
parent 129 d48946d164c6
child 168 ea92f4fe783d
permissions -rw-r--r--
Adding class for specific css in App, Navbar and SessionList components

import { put } from 'redux-saga/effects'
import Immutable from 'immutable';

export const SyncMixin = Base => class extends Base {

  constructor(syncEntries, client) {
    super();
    this.syncEntries = syncEntries;
    this.client = client;
    this.localDiffs = null;
  }

  // abstract methods

  // local diffs (immutable)
  // getLocalDiffs()

  // remote urls
  // getRemoteLoadUrl()
  // getRemoteDeleteUrl(localObjInst);
  // getRemoteCreateUrl(localObjInst)
  // getRemoteUpdateUrl(localObjInst)

  // build remote json message
  // getRemoteData(localObjInst)
  // getLocalRecord(remoteObj)

  // actions
  // doDeleteLocalObj(localObjId);
  // resetLocalObj(localObjInst)
  // loadObj(objRecord)


  * loadFromRemote() {

    const objIds = this.syncEntries
      .filter((syncEntry) => syncEntry.action !== 2)
      .map((syncEntry) => syncEntry.ext_id);

    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(this.localDiffs.get('deleted').has(remoteObj.ext_id)) {
        // The session has been deleted locally, we will delete it later
        continue;
      }

      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
        const newCreatedMap = this.localDiffs.get('created').delete(remoteObj.ext_id);
        this.localDiffs = this.localDiffs.set('created', newCreatedMap);
      }

      if(this.localDiffs.get('updated').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
        const newModifiedMap = this.localDiffs.get('updated').delete(remoteObj.ext_id);
        this.localDiffs = this.localDiffs.set('updated', newModifiedMap);
      }

      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 = this.localDiffs.get('deleted');
    let updatedObjs = this.localDiffs.get('updated');
    let createdObjs = this.localDiffs.get('created');
    for (var objId of objToDelete) {
      if(deleteObjs.has(objId)) {
        // we remove it from the list of sessions to delete
        deleteObjs = deleteObjs.delete(objId);
      }
      if(updatedObjs.has(objId)) {
        updatedObjs = updatedObjs.delete(objId);
      }
      if(createdObjs.has(objId)) {
        createdObjs = createdObjs.delete(objId);
      }
      yield put(this.doDeleteLocalObj(objId));
    }
    this.localDiffs = Immutable.Map({created: createdObjs, updated: updatedObjs, deleted: deleteObjs});
  }

  * syncObjects() {

    this.localDiffs = yield this.getLocalDiffs();

    yield this.loadFromRemote();
    yield this.deleteFromRemote();

    let localObjInst;

    // delete remote obj
    for(localObjInst of this.localDiffs.get('deleted').values()) {

      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.get('_id')));
    }

    for(localObjInst of this.localDiffs.get('created').values()) {
      const remoteData = this.getRemoteData(localObjInst);
      //TODO: SET VERSION !!!!
      yield this.client.post(this.getRemoteCreateUrl(localObjInst), remoteData);
      yield put(this.resetLocalObj(localObjInst));
    }

    for(localObjInst of this.localDiffs.get('updated').values()) {
      const remoteData = this.getRemoteData(localObjInst);
      //TODO: SET VERSION !!!!
      yield this.client.put(this.getRemoteUpdateUrl(localObjInst), remoteData);
      yield put(this.resetLocalObj(localObjInst));
    }

  }
}

export default SyncMixin;