Fix local conflict resolution in browser example

This commit is contained in:
Ritchie Martori 2014-02-13 07:40:09 -08:00
parent 49935b1b8a
commit dfe7f4bb1b
5 changed files with 1677 additions and 776 deletions

2343
dist/loopback.js vendored

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
// client app
var app = loopback();
// remote models
app.dataSource('api', {
connector: loopback.Server,
host: 'localhost',
@ -9,6 +10,7 @@ app.dataSource('api', {
discover: loopback.remoteModels
});
// local storage
app.dataSource('local', {
connector: loopback.Memory
});
@ -22,19 +24,22 @@ var network = {
return this.available ? 'on' : 'off';
}
};
// get the remote model "Color"
var Color = loopback.getModel('Color');
// define a local model for offline data
var LocalColor = app.model('LocalColor', {
dataSource: 'local',
options: {trackChanges: true}
});
// generate a random client id
LocalColor.beforeCreate = function(next, color) {
color.id = Math.random().toString().split('.')[1];
next();
}
var localConflicts = [];
function ReplicationCtlr($scope) {
var interval = 1000;
var remoteIntervalId;
@ -52,6 +57,13 @@ function ReplicationCtlr($scope) {
});
}
$scope.resolveUsingLocal = function(conflict) {
conflict.resolve(function(err) {
if(err) return console.log('resolveUsingLocal', err);
conflict.source.save();
});
}
LocalColor.on('deleted', replicate);
LocalColor.on('changed', replicate);
LocalColor.on('deletedAll', replicate);
@ -63,6 +75,7 @@ function ReplicationCtlr($scope) {
if(network.available) {
LocalColor.currentCheckpoint(function(err, cp) {
if(err) alert('Replication Error:', err.message);
setTimeout(function() {
LocalColor.replicate(cp, Color, {}, function(err, conflicts) {
conflicts.forEach(function(conflict) {
@ -86,21 +99,20 @@ function ReplicationCtlr($scope) {
if(network.available) {
Color.currentCheckpoint(function(err, cp) {
Color.replicate(cp, LocalColor, {}, function(err, conflicts) {
if(err) alert('Replication from Remote Error:', err.message);
});
});
}
}
// get initial data
replicateFromRemote();
}
function NetworkCtrl($scope) {
$scope.network = network;
}
function ConflictCtrl($scope) {
$scope.conflicts = localConflicts;
}
function ListCtrl($scope) {
LocalColor.on('changed', update);
LocalColor.on('deleted', update);
@ -119,35 +131,3 @@ function ListCtrl($scope) {
update();
}
function ChangeCtrl($scope) {
var Change = LocalColor.getChangeModel();
Change.on('changed', update);
Change.on('deleted', update);
function update() {
Change.find({order: 'checkpoint ASC'}, function(err, changes) {
$scope.changes = changes;
$scope.$apply();
});
}
update();
}
function RemoteChangeCtrl($scope) {
var Change = Color.getChangeModel();
setInterval(update, 5000);
function update() {
Change.find({order: 'checkpoint ASC'}, function(err, changes) {
$scope.changes = changes;
$scope.$apply();
});
}
update();
}

View File

@ -10,15 +10,17 @@
<h1 ng-controller="NetworkCtrl">
<input style="font-size: 48px;" type="checkbox" ng-model="network.available" />Online
</h1>
<ul ng-controller="ReplicationCtlr">
<button ng-click="replicate()">Push</button>
<button ng-click="replicateFromRemote()">Pull</button>
<h2 ng-show="conflicts.length">Conflicts:</h2>
<li ng-repeat="conflict in conflicts">
<button ng-click="conflict.resolve()">Use local {{conflict.source.name}}</button>
<button ng-click="resolveUsingRemote(conflict)">Use remote {{conflict.target.name}}</button>
<button ng-click="resolveUsingLocal(conflict)">Use local {{conflict.source.name || "(removed)"}}</button>
<button ng-click="resolveUsingRemote(conflict)">Use remote {{conflict.target.name || "(removed)"}}</button>
</li>
</ul>
<ul ng-controller="ListCtrl">
<li ng-repeat="color in colors" style="color: {{color.name}}">
<form ng-submit="color.save()">
@ -34,47 +36,6 @@
</li>
</ul>
<h1>Local Changes</h1>
<table ng-controller="ChangeCtrl">
<thead>
<th>type</th>
<th>rev</th>
<th>prev</th>
<th>base</th>
<th>checkpoint</th>
<th>modelId</th>
</thead>
<tr ng-repeat="change in changes">
<td>{{change.type()}}</h3>
<td>{{change.rev}}</td>
<td>{{change.prev}}</td>
<td>{{change.base}}</td>
<td>{{change.checkpoint}}</td>
<td>{{change.modelId}}</td>
</tr>
</table>
<h1>Remote Changes</h1>
<table ng-controller="RemoteChangeCtrl">
<thead>
<th>type</th>
<th>rev</th>
<th>prev</th>
<th>base</th>
<th>checkpoint</th>
<th>modelId</th>
</thead>
<tr ng-repeat="change in changes">
<td>{{change.type()}}</h3>
<td>{{change.rev}}</td>
<td>{{change.prev}}</td>
<td>{{change.base}}</td>
<td>{{change.checkpoint}}</td>
<td>{{change.modelId}}</td>
</tr>
</table>
<script src="loopback.js"></script>
<script src="loopback-remote-models.js"></script>
<script src="client.js"></script>

View File

@ -236,7 +236,8 @@ ServerConnector.prototype.updateOrCreate = function updateOrCreate(model, data,
ServerConnector.prototype.destroy = function destroy(model, id, callback) {
this.requestModelById(model, id, {
method: 'DELETE'
method: 'DELETE',
json: false
}, callback);
};

View File

@ -523,8 +523,6 @@ Model.setBaseRevisions = function(updates, callback) {
var idName = this.dataSource.idName(this.modelName);
var Change = this.getChangeModel();
console.log('setBaseRevisions');
updates.forEach(function(update) {
tasks.push(function(cb) {
Change.findById(update.change.id, function(err, change) {